《OpenGL编程指南》第11章——Double

编程入门 行业动态 更新时间:2024-10-03 17:07:22

《OpenGL编程<a href=https://www.elefans.com/category/jswz/34/1769915.html style=指南》第11章——Double"/>

《OpenGL编程指南》第11章——Double

本案例主要讲解在Shader中如何使用图像(Images)对象。
案例通过创建了一维纹理Buffer(TBO)用来作为颜色数据,通过绘制多个圆柱体,将绘制结果缓存到另一个Image中,再在后续的模型绘制中使用该图像数据。
程序的主要执行流程:
###1 创建TBO对象,用于保存1D 纹理数据:

	GLuint m_image_palette_buffer; // 纹理缓冲区对象GLuint m_image_palette_texture; //纹理 

2. 创建输出纹理

	// 输出纹理,渲染第一阶段,在shader中写入数据,渲染第二阶段,在shader中读取数据GLuint m_output_texture;   // Output iamge and PBO for clear it GLuint m_output_texture_clear_buffer;

3. 绘制流程:

  • 绑定m_iamge_palette_texture绑定到0号绑定点的图像对象,用于Shader中读取数据
  • 使用m_output_texture_clear_buffer,清空m_output_texture中的数据
  • 将m_output_texture绑定到1号绑定点的图像对象
  • 设置投影、模型、视图矩阵
  • 禁用颜色缓冲区,绘制多个圆柱体,通过shader,将颜色数据写入到m_output_texture中。
  • 将m_output_texture绑定到0号绑定点的图像对象
  • 绘制四边形

主要代码:

	// DoubleWrite.cpp#include <vapp.h>#include <vutils.h>#include <LoadShaders.h>#include <vbm.h>#include <vmath.h>#include <stdio.h>#include <iostream>#define MAX_FRAMEBUFFER_WIDTH 1024#define MAX_FRAMEBUFFER_HEIGHT 1024BEGIN_APP_DECLARATION(DoubleWrite)virtual void Initialize(const char* title);virtual void Display(bool auto_redraw);virtual void Finalize();virtual void Reshape(int width, int height);void InitShaders();void InitBuffers();private:// Color palette buffer texture  TBO GLuint m_image_palette_buffer; // 纹理缓冲区对象GLuint m_image_palette_texture; //纹理 // 输出纹理,渲染第一阶段,在shader中写入数据,渲染第二阶段,在shader中读取数据GLuint m_output_texture;   // Output iamge and PBO for clear it GLuint m_output_texture_clear_buffer;GLuint m_render_program; // 渲染模型着色器GLuint m_resolve_program; // 重显示着色器GLuint m_quad_vao;GLuint m_quad_vbo;GLuint m_xfb;GLfloat m_aspect;GLuint m_projection_matrix_loc;GLuint m_model_matrix_loc;GLuint m_view_matrix_loc;GLuint m_aspect_loc;GLuint m_time_loc;VBObject m_object;float m_current_height;float m_current_width;END_APP_DECLARATION()DEFINE_APP(DoubleWrite, "DoubleWrite")void DoubleWrite::InitShaders(){ShaderInfo render_shaders[] = {{GL_VERTEX_SHADER,"Media/Shaders/11/DoubleWrite.vs.glsl"},{GL_FRAGMENT_SHADER,"Media/Shaders/11/DoubleWrite.fs.glsl"},{GL_NONE,NULL} };m_render_program = LoadShaders(render_shaders);m_model_matrix_loc = glGetUniformLocation(m_render_program,"model_matrix");m_view_matrix_loc = glGetUniformLocation(m_render_program,"view_matrix");m_projection_matrix_loc = glGetUniformLocation(m_render_program,"projection_matrix");ShaderInfo blit_shaders[] = {{GL_VERTEX_SHADER,"Media/shaders/11/DoubleWrite_blit.vs.glsl"},{GL_FRAGMENT_SHADER,"Media/shaders/11/DoubleWrite_blit.fs.glsl"},{GL_NONE,NULL}};m_resolve_program = LoadShaders(blit_shaders);}void DoubleWrite::InitBuffers(){// TBOglGenBuffers(1,&m_image_palette_buffer);glBindBuffer(GL_TEXTURE_BUFFER,m_image_palette_buffer); // glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);glBufferData(GL_TEXTURE_BUFFER,256*4*sizeof(float),NULL,GL_STATIC_DRAW); // 此处分配内存大小类似于一个1D纹理,使用256*1 的GL_RGBA32F,每个颜色一个float(4字节 4*8=32bit)glGenTextures(1,&m_image_palette_texture);glBindTexture(GL_TEXTURE_BUFFER,m_image_palette_texture); // 将纹理绑定到纹理缓冲区对象glTexBuffer(GL_TEXTURE_BUFFER,GL_RGBA32F,m_image_palette_buffer);vmath::vec4* data = (vmath::vec4*)glMapBuffer(GL_TEXTURE_BUFFER,GL_WRITE_ONLY);for(int i = 0; i < 256; i++){// 初始化1D纹理数据//data[i] = vmath::vec4((float)i);data[i] = vmath::vec4((float)i, (float)(256-i),(float)(rand()&0xFFFF),1.0f);}glUnmapBuffer(GL_TEXTURE_BUFFER);// create output textureglActiveTexture(GL_TEXTURE0);glGenTextures(1,&m_output_texture);glBindTexture(GL_TEXTURE_2D,m_output_texture);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);// glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA32F,MAX_FRAMEBUFFER_WIDTH,MAX_FRAMEBUFFER_HEIGHT,0,GL_RGBA,GL_FLOAT,NULL);glBindTexture(GL_TEXTURE_2D,0);// (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);// glBindImageTexture(GLuint unit, GLuint texture, GLint level, GLboolean layerd, GLint layer, GLenum acces, GLenum format);glBindImageTexture(0,m_output_texture,0,GL_TRUE,0,GL_READ_WRITE,GL_RGBA32F); // 绑定 ImageglGenBuffers(1,&m_output_texture_clear_buffer);glBindBuffer(GL_PIXEL_UNPACK_BUFFER,m_output_texture_clear_buffer); // 从buffer -->> Framebuffer or texture buffer// 对buffer 分配空间 ,红宝书使用GLuint,改成GLFloat也是可以的glBufferData(GL_PIXEL_UNPACK_BUFFER,MAX_FRAMEBUFFER_WIDTH*MAX_FRAMEBUFFER_HEIGHT* 4 *sizeof(GLfloat),NULL,GL_STATIC_DRAW); data = (vmath::vec4*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER,GL_WRITE_ONLY);memset(data,0x00,MAX_FRAMEBUFFER_HEIGHT*MAX_FRAMEBUFFER_WIDTH * 4 *sizeof(GLfloat));glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);// creat  vao static const GLfloat quad_vertices[] = {-1.0f, -1.0f,1.0f, -1.0f,-1.0f,  1.0f,1.0f,  1.0f,};glGenVertexArrays(1,&m_quad_vao);glGenBuffers(1,&m_quad_vbo);glBindVertexArray(m_quad_vao);glBindBuffer(GL_ARRAY_BUFFER,m_quad_vbo);glBufferData(GL_ARRAY_BUFFER,sizeof(quad_vertices),quad_vertices,GL_STATIC_DRAW);glVertexAttribPointer(0,2,GL_FLOAT,GL_FALSE,0,NULL);glEnableVertexAttribArray(0);glClearDepth(1.0f);glBindVertexArray(0);}void DoubleWrite::Initialize(const char* title){base::Initialize(title);InitShaders();InitBuffers();std::string filePath = Utils::instance()->getMediaPath() + "Media/unit_pipe.vbm";m_object.LoadFromVBM(filePath.c_str(),0,1,2);}void DoubleWrite::Display(bool auto_redraw){float t = float(GetTickCount() & 0xFFFF)/0x3FFF;static vmath::vec3 X(1.0f, 0.0f, 0.0f);static vmath::vec3 Y(0.0f, 1.0f, 0.0f);static vmath::vec3 Z(0.0f, 0.0f, 1.0f);glDisable(GL_DEPTH_TEST);glDisable(GL_CULL_FACE);glClearColor(0.0f, 0.0f, 0.0f, 0.0f);glClear(GL_COLOR_BUFFER_BIT);// bind palette buffer//glBindBuffer(GL_TEXTURE_BUFFER,m_image_palette_buffer);//绑定图像数据到0上glBindImageTexture(0,m_image_palette_texture,0,GL_FALSE,0,GL_READ_ONLY,GL_RGBA32F);// clear output image  使用 m_output_texture_clear_buffer中的数据,重新覆盖m_output_texture中的数据,即清空原有数据,准备重新写入。glBindBuffer(GL_PIXEL_UNPACK_BUFFER,m_output_texture_clear_buffer);glBindTexture(GL_TEXTURE_2D,m_output_texture);glTexSubImage2D(GL_TEXTURE_2D,0,0,0,m_current_width,m_current_height,GL_RGBA,GL_FLOAT,NULL);glBindTexture(GL_TEXTURE_2D,0);//Bind output image for read-write// 绑定图像数据到1上glBindImageTexture(1,m_output_texture,0,GL_FALSE,0,GL_READ_WRITE,GL_RGBA32F);vmath::mat4 model_matrix = vmath::translate(0.0f, 0.0f, -15.0f) *vmath::rotate(t * 360.0f, 0.0f, 0.0f, 1.0f) *vmath::rotate(t * 435.0f, 0.0f, 1.0f, 0.0f) *vmath::rotate(t * 275.0f, 1.0f, 0.0f, 0.0f);vmath::mat4 view_matrix = vmath::mat4::identity();vmath::mat4 projection_matrix = vmath::frustum(-1.0f, 1.0f, m_aspect, -m_aspect, 1.0f, 40.f);glUseProgram(m_render_program);glUniformMatrix4fv(m_projection_matrix_loc,1,GL_FALSE,projection_matrix);glUniformMatrix4fv(m_model_matrix_loc,1,GL_FALSE,model_matrix);glUniformMatrix4fv(m_view_matrix_loc,1,GL_FALSE,view_matrix);/*glColorMask, glColorMaski — enable and disable writing of frame buffer color componentsvoid glColorMask(	GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha);*/// 禁止写入颜色缓存glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);	m_object.Render(0,4 * 4 * 4);// 启用写入颜色缓存glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);glBindImageTexture(0,m_output_texture,0,GL_FALSE,0,GL_READ_ONLY,GL_RGBA32F);glBindVertexArray(m_quad_vao);glUseProgram(m_resolve_program);glDrawArrays(GL_TRIANGLE_STRIP,0,4);base::Display(auto_redraw);}void DoubleWrite::Finalize(){glUseProgram(0);glDeleteVertexArrays(1,&m_quad_vao);glDeleteBuffers(1,&m_quad_vbo);}void DoubleWrite::Reshape(int width, int height){m_aspect  = GLfloat(width)/height;glViewport(0,0,width,height);m_current_width = width;m_current_height = height;}

更多推荐

《OpenGL编程指南》第11章——Double

本文发布于:2024-02-28 05:24:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1768297.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:指南   OpenGL   Double

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!