当前位置: 首页 > news >正文

OGL(教程35)——延迟渲染1——代码结构梳理

项目代码:git@gitee.com:yichichunshui/DeferredRendering1.git


int main(int argc, char** argv)
{
    Magick::InitializeMagick(*argv);
    GLUTBackendInit(argc, argv);

    if (!GLUTBackendCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, 32, false, "Tutorial 35")) {
        return 1;
    }
    
    SRANDOM;

首先是读取图片库的初始化;然后是初始化窗口的显示设置;然后初始化窗口;

Tutorial35* pApp = new Tutorial35();
 Tutorial35() 
    {
        m_pGameCamera = NULL;
        m_scale = 0.0f;

        m_persProjInfo.FOV = 60.0f;
        m_persProjInfo.Height = WINDOW_HEIGHT;
        m_persProjInfo.Width = WINDOW_WIDTH;
        m_persProjInfo.zNear = 1.0f;
        m_persProjInfo.zFar = 100.0f;  
        
        m_frameCount = 0;
        m_fps = 0.0f;
        
        m_time = glutGet(GLUT_ELAPSED_TIME);
    }

一些初始化的操作。

if (!pApp->Init()) {
        return 1;
    }

初始化。

bool Init()
    {
        if (!m_gbuffer.Init(WINDOW_WIDTH, WINDOW_HEIGHT)) {
            return false;
        }

看下gbuffer的Init方法。

bool GBuffer::Init(unsigned int WindowWidth, unsigned int WindowHeight)
{
    // Create the FBO
    glGenFramebuffers(1, &m_fbo);    
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);

创建帧缓冲对象,绑定帧缓冲对象到GL_DRAW_FRAMEBUFFER目标。

    // Create the gbuffer textures
    glGenTextures(ARRAY_SIZE_IN_ELEMENTS(m_textures), m_textures);
	glGenTextures(1, &m_depthTexture);

创建一个纹理数组,创建一个深度纹理。

  for (unsigned int i = 0 ; i < ARRAY_SIZE_IN_ELEMENTS(m_textures) ; i++) {
    	glBindTexture(GL_TEXTURE_2D, m_textures[i]);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, WindowWidth, WindowHeight, 0, GL_RGB, GL_FLOAT, NULL);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, m_textures[i], 0);
    }

对每个纹理绑定,绑定目标为2D格式图片,为每个纹理分配内存,将每个纹理绑定到帧缓冲,以及设置其附件类型为GL_COLOR_ATTACHMENT0+i。

// depth
	glBindTexture(GL_TEXTURE_2D, m_depthTexture);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, WindowWidth, WindowHeight, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthTexture, 0);

绑定深度缓冲到2D格式,为深度纹理分配内存,绑定深度纹理到帧缓冲,设置其附件类型为GL_DEPTH_ATTACHMENT。

GLenum DrawBuffers[] = { GL_COLOR_ATTACHMENT0, 
						     GL_COLOR_ATTACHMENT1,
						     GL_COLOR_ATTACHMENT2,
						     GL_COLOR_ATTACHMENT3 };

需要绘制四个类型的附件:分别是:

 enum GBUFFER_TEXTURE_TYPE {
        GBUFFER_TEXTURE_TYPE_POSITION, //对应GL_COLOR_ATTACHMENT0,位置
        GBUFFER_TEXTURE_TYPE_DIFFUSE, //对应GL_COLOR_ATTACHMENT1,漫反射贴图
        GBUFFER_TEXTURE_TYPE_NORMAL, //对应GL_COLOR_ATTACHMENT2,法线
        GBUFFER_TEXTURE_TYPE_TEXCOORD, //GL_COLOR_ATTACHMENT1,纹理坐标
        GBUFFER_NUM_TEXTURES //最后一个表示纹理数量,这里为4
    };
    glDrawBuffers(ARRAY_SIZE_IN_ELEMENTS(DrawBuffers), DrawBuffers);

绘制四个贴图。

 GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    if (Status != GL_FRAMEBUFFER_COMPLETE) {
        printf("FB error, status: 0x%x\n", Status);
        return false;
    }

检查帧缓冲状态。

	// restore default FBO
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

解绑当前自创建的缓冲,也就是恢复到默认的帧缓冲,

回到main的Init方法:

 m_pGameCamera = new Camera(WINDOW_WIDTH, WINDOW_HEIGHT);

创建相机。

 if (!m_DSGeomPassTech.Init()) {
            printf("Error initializing DSGeomPassTech\n");
            return false;
        }      

延迟渲染的几何阶段初始化:

bool DSGeomPassTech::Init()
{
    if (!CompileProgram("GeometryPass")) {
        return false;
    }

编译程序GeometryPass程序,这个字符串在哪里,实际上我们要看下DSGeomPassTech的构造函数:

DSGeomPassTech::DSGeomPassTech() : Technique("shaders/geometry_pass.glsl")
{   
}

基类为Technique:


Technique::Technique(const char* pEffectFile)
{
    m_pEffectFile = pEffectFile;
    m_shaderProg = 0;
    m_effect = glfxGenEffect();
}

这个geometry_pass.glsl中的代码:

interface VSOutput
{
    vec3 WorldSpacePos;
    vec2 TexCoord;
    vec3 Normal;  
};


uniform mat4 gWVP;
uniform mat4 gWorld;
                                        
shader VSmain(in vec3 Pos, in vec2 TexCoord, in vec3 Normal, out VSOutput VSout)         
{       
    gl_Position         = gWVP * vec4(Pos, 1.0);
    VSout.TexCoord      = TexCoord;                  
    VSout.Normal        = (gWorld * vec4(Normal, 0.0)).xyz;   
    VSout.WorldSpacePos = (gWorld * vec4(Pos, 1.0)).xyz;   
};


struct FSOutput
{                   
    vec3 WorldSpacePos;    
    vec3 Diffuse;     
    vec3 Normal;      
    vec3 TexCoord;    
};
											
uniform sampler2D gColorMap;                
											
shader FSmain(in VSOutput FSin, out FSOutput FSout)									
{											
	FSout.WorldSpacePos = FSin.WorldSpacePos;					
	FSout.Diffuse      = texture(gColorMap, FSin.TexCoord).xyz;	
	FSout.Normal       = normalize(FSin.Normal);					
	FSout.TexCoord     = vec3(FSin.TexCoord, 0.0);				
};

program GeometryPass
{
    vs(410)=VSmain();
    fs(410)=FSmain();
};

GLSL语言,书写的shader程序。
顶点着色器的输出是:位置、纹理坐标、法线、世界坐标。
片段着色器的输出是:世界坐标、漫反射、法线、纹理坐标。

这就是要输出四个颜色值。

m_WVPLocation = GetUniformLocation("gWVP");
m_WorldMatrixLocation = GetUniformLocation("gWorld");
m_colorTextureUnitLocation = GetUniformLocation("gColorMap");

得到属性的位置:gWVP、gWorld、gColorMap

if (m_WVPLocation == INVALID_UNIFORM_LOCATION ||
		m_WorldMatrixLocation == INVALID_UNIFORM_LOCATION ||
		m_colorTextureUnitLocation == INVALID_UNIFORM_LOCATION) {
			return false;
	}

	return true;
}

判断获取是否出错。

回到main函数的Init方法:

m_DSGeomPassTech.Enable();
m_DSGeomPassTech.SetColorTextureUnit(COLOR_TEXTURE_UNIT_INDEX);

//#define COLOR_TEXTURE_UNIT_INDEX 0

 if (!m_mesh.LoadMesh("../Content/phoenix_ugv.md2")) {
			return false;
		}

#ifdef FREETYPE
        if (!m_fontRenderer.InitFontRenderer()) {
            return false;
        }
#endif
        
        return true;
    }

加载模型。

看函数:RenderSceneCB()

void DSGeometryPass()
    {
		m_DSGeomPassTech.Enable();

        m_gbuffer.BindForWriting();

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		Pipeline p;
        p.Scale(0.1f, 0.1f, 0.1f);
        p.Rotate(0.0f, m_scale, 0.0f);
        p.WorldPos(-0.8f, -1.0f, 12.0f);
        p.SetCamera(m_pGameCamera->GetPos(), m_pGameCamera->GetTarget(), m_pGameCamera->GetUp());
        p.SetPerspectiveProj(m_persProjInfo);
        m_DSGeomPassTech.SetWVP(p.GetWVPTrans());        
		m_DSGeomPassTech.SetWorldMatrix(p.GetWorldTrans());
        m_mesh.Render();       
    }

这个样之后,颜色都被存储在缓冲中了。
下面就是读取并展示出来:

  void DSLightPass()
    {       
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
      
        m_gbuffer.BindForReading();
        
        GLint HalfWidth = (GLint)(WINDOW_WIDTH / 2.0f);
        GLint HalfHeight = (GLint)(WINDOW_HEIGHT / 2.0f);
        
        m_gbuffer.SetReadBuffer(GBuffer::GBUFFER_TEXTURE_TYPE_POSITION);
        glBlitFramebuffer(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0, HalfWidth, HalfHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);

        m_gbuffer.SetReadBuffer(GBuffer::GBUFFER_TEXTURE_TYPE_DIFFUSE);
        glBlitFramebuffer(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, HalfHeight, HalfWidth, WINDOW_HEIGHT, GL_COLOR_BUFFER_BIT, GL_LINEAR);

        m_gbuffer.SetReadBuffer(GBuffer::GBUFFER_TEXTURE_TYPE_NORMAL);
        glBlitFramebuffer(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, HalfWidth, HalfHeight, WINDOW_WIDTH, WINDOW_HEIGHT, GL_COLOR_BUFFER_BIT, GL_LINEAR);

        m_gbuffer.SetReadBuffer(GBuffer::GBUFFER_TEXTURE_TYPE_TEXCOORD);
        glBlitFramebuffer(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, HalfWidth, 0, WINDOW_WIDTH, HalfHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);	
    }

最终结果为:
在这里插入图片描述

相关文章:

  • 安装MySQL_安装Navicat_启动数据库服务
  • android studio查看android手机日志
  • Python02(Linux命令)
  • luaforwindws安装与调用方式
  • vs添加链接文件
  • httpclient
  • 继成ScriptableObject的静态类对象竟然没有销毁
  • 国内镜像站
  • unity地形
  • Excel催化剂开源第5波-任务窗格在OFFICE2013中新建文档不能同步显示问题解决
  • shader 顶点属性——颜色
  • unity shader projector使用
  • python os walk 讲的太清楚了 有图片
  • 日志logging
  • 用世界矩阵变换局部坐标,得到世界坐标
  • [case10]使用RSQL实现端到端的动态查询
  • 【140天】尚学堂高淇Java300集视频精华笔记(86-87)
  • 08.Android之View事件问题
  • 2017年终总结、随想
  • 2019.2.20 c++ 知识梳理
  • express + mock 让前后台并行开发
  • HTML-表单
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • iOS高仿微信项目、阴影圆角渐变色效果、卡片动画、波浪动画、路由框架等源码...
  • Java应用性能调优
  • KMP算法及优化
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • LeetCode541. Reverse String II -- 按步长反转字符串
  • Python 反序列化安全问题(二)
  • Redis提升并发能力 | 从0开始构建SpringCloud微服务(2)
  • SOFAMosn配置模型
  • TypeScript迭代器
  • vue学习系列(二)vue-cli
  • 编写符合Python风格的对象
  • 产品三维模型在线预览
  • 从零开始学习部署
  • 给github项目添加CI badge
  • 将回调地狱按在地上摩擦的Promise
  • 怎么将电脑中的声音录制成WAV格式
  • 中文输入法与React文本输入框的问题与解决方案
  • #pragma data_seg 共享数据区(转)
  • #我与Java虚拟机的故事#连载07:我放弃了对JVM的进一步学习
  • (03)光刻——半导体电路的绘制
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (8)STL算法之替换
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)spring boot智能服药提醒app 毕业设计 102151
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (简单) HDU 2612 Find a way,BFS。
  • (亲测)设​置​m​y​e​c​l​i​p​s​e​打​开​默​认​工​作​空​间...
  • .NET CF命令行调试器MDbg入门(三) 进程控制
  • .NET Core 和 .NET Framework 中的 MEF2
  • .vimrc php,修改home目录下的.vimrc文件,vim配置php高亮显示