【OpenGL】多重采样案例MSAA
发布日期:2021-05-10 02:21:16 浏览次数:19 分类:精选文章

本文共 26759 字,大约阅读时间需要 89 分钟。

 示例图暂缺(目前运行exe失败,后期补充)

本文比较难,个人来说还不是完全弄懂。

#version 150 // hdr_bloom.vs// outputs MVP transformed position // passes texture coordinates through// color is * by normal and passed on.in vec3 vVertex;in vec3 vNormal;in vec2 vTexCoord0;uniform mat4 mvMatrix;uniform mat4 pMatrix;uniform vec3 vLightPos;uniform vec4 vColor;out vec4 vFragColor;out vec2 vTexCoord;void main(void) { 	mat3 mNormalMatrix;	mNormalMatrix[0] = normalize(mvMatrix[0].xyz);	mNormalMatrix[1] = normalize(mvMatrix[1].xyz);	mNormalMatrix[2] = normalize(mvMatrix[2].xyz);		vec3 vNorm = normalize(mNormalMatrix * vNormal);		vec4 ecPosition;	vec3 ecPosition3;	ecPosition = mvMatrix * vec4(vVertex, 1.0);	ecPosition3 = ecPosition.xyz /ecPosition.w;	vec3 vLightDir = normalize(vLightPos - ecPosition3);	float fDot = max(0.0, dot(vNorm, vLightDir)); 	vFragColor.rgb = vColor.rgb * fDot;	vFragColor.a = vColor.a;	vTexCoord = vTexCoord0;	mat4 mvpMatrix;	mvpMatrix = pMatrix * mvMatrix;	gl_Position = mvpMatrix * vec4(vVertex, 1.0); }

 处理曝光效果的顶点着色器如上,大致内容就是转换顶点空间和获得纹理坐标以及传给片段着色器的漫反射颜色值

#version 150 // color.fs// outputs 1 color interpolated from VS// in vec4 vFragColor; in vec2 vTexCoord; uniform sampler2D textureUnit0; uniform vec4 vColor;out vec4 oColor;out vec4 oBright;void main(void) { 	const float bloomLimit = 1.0;        oColor =  vFragColor;        vec3 brightColor = max(vColor.rgb - vec3(bloomLimit), vec3(0.0));    float bright = dot(brightColor, vec3(1.0));    bright = smoothstep(0.0, 0.5, bright);    oBright.rgb = mix(vec3(0.0), vColor.rgb, bright).rgb;    oBright.a = 1.0;}

 专门获取一个自定义颜色图和亮度图的片段着色器 和 前一个案例HDR_Bloom一样

#version 150 // hdr_exposure.fs// Scale floating point texture to 0.0 - 1.0 based // on the specified exposure// Resolve multisample buffer based on input sample count// in vec2 vTexCoord;uniform sampler2DMS origImage;uniform samplerBuffer sampleWeightSampler; uniform int sampleCount; // 0-based, 0=1sample, 1=2samples, etcuniform int useWeightedResolve; // 0-false, 1-trueuniform float exposure;out vec4 oColor;// do all tone mapping in a separate functionvec4 toneMap(vec4 vHdrColor){	vec4 vLdrColor;	vLdrColor = 1.0 - exp2(-vHdrColor * exposure);	vLdrColor.a = 1.0f;	return vLdrColor;}void main(void) {     // Calculate un-normalized texture coordinates	vec2 tmp = floor(textureSize2DMS(origImage) * vTexCoord);     // Find both the weighted and unweighted colors	vec4 vColor = vec4(0.0, 0.0, 0.0, 1.0);	vec4 vWeightedColor = vec4(0.0, 0.0, 0.0, 1.0);		for (int i = 0; i <= sampleCount; i++)	{	    // Get the weight for this sample from the texBo, this changes	    // based on the number of samples	    float weight = texelFetch(sampleWeightSampler, i).r;	    	    // tone-map the HDR texel before it is weighted	    vec4 sample = toneMap(texelFetch(origImage, ivec2(tmp), i));	    		vWeightedColor += sample * weight;		vColor += sample;	}    // now, decide on the type of resolve to perform    oColor = vWeightedColor;		// if the user selected the unweighed resolve, output the 	// equally weighted value	if (useWeightedResolve != 0)	{	    oColor = vColor / (sampleCount+1);    	}    oColor.a = 1.0f;    }

 处理多重采样的片段着色器,先映射纹理坐标到多重采样图像范围(它变为整数)接着从sampleWeightSampler纹理缓冲区获取权值,权值是位像素距离归一化数值,一共进行sampleCount次采样权值 并且也同样地进行从origImage多重采样纹理获取颜色值,并累加到vColor上,累加到vWeightedColor会乘上对应的位像素权值,最终以useWeightedResolve不为0则以vColor求平均值输出,否则则是输出vWeightedColor。关于这种乘以权值的操作是称之为卷积的,它最终所有数值相加到一起会是一个不超过1范围的值。

#version 150 // tex_replace.fs// outputs 1 color using texture replace// in vec2 vTexCoord; uniform sampler2D textureUnit0; uniform vec4 vColor;out vec4 oColor;out vec4 oBright;void main(void) {	const float bloomLimit = 1.0;     oColor =  vColor*texture(textureUnit0, vTexCoord);    oColor.a = 1.0;        vec3 brightColor = max(vColor.rgb - vec3(bloomLimit), vec3(0.0));    float bright = dot(brightColor, vec3(1.0));    bright = smoothstep(0.0, 0.5, bright);    oBright.rgb = mix(vec3(0.0), vColor.rgb, bright).rgb;    oBright.a = 1.0;}

 与color.fs区别在于,oColor是HDR图像颜色。

C++代码如下:

#pragma comment(lib, "gltools.lib")#include 
#include
#include
// OpenEXR headers#include
#include
#include
#include
#include
#include
#include
#include
#ifdef __APPLE__#include
#else#define FREEGLUT_STATIC#include
#endif#ifdef _WIN32#pragma comment (lib, "half.lib") #pragma comment (lib, "Iex.lib")#pragma comment (lib, "IlmImf.lib")#pragma comment (lib, "IlmThread.lib")#pragma comment (lib, "Imath.lib")#pragma comment (lib, "zlib.lib")#endif#pragma warning( disable : 4244)static GLfloat vWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };static GLfloat vWhiteX2[] = { 2.0f, 2.0f, 2.0f, 2.0f };static GLfloat vLtGrey[] = { 0.75f, 0.75f, 0.75f, 1.0f };static GLfloat vLightPos[] = { -2.0f, 3.0f, -2.0f, 1.0f };static GLfloat vSkyBlue[] = { 0.260f, 0.476f, 0.925f, 1.0f };static const GLenum windowBuff[] = { GL_BACK_LEFT };static const GLenum fboBuffs[] = { GL_COLOR_ATTACHMENT0 };GLsizei screenWidth; // Desired window or desktop widthGLsizei screenHeight; // Desired window or desktop heightGLboolean bFullScreen; // Request to run full screenGLboolean bAnimated; // Request for continual updatesGLMatrixStack modelViewMatrix; // Modelview MatrixGLMatrixStack projectionMatrix; // Projection MatrixGLFrustum viewFrustum; // View FrustumGLGeometryTransform transformPipeline; // Geometry Transform PipelineGLFrame cameraFrame; // Camera frameGLBatch screenQuad;M3DMatrix44f orthoMatrix;GLBatch floorBatch;GLBatch windowBatch;GLBatch windowBorderBatch;GLBatch windowGridBatch;GLuint flatColorProg;GLuint texReplaceProg;GLuint hdrResolve;GLuint blurProg;GLuint hdrFBO[1];GLuint brightPassFBO[4];GLuint textures[1];GLuint hdrTextures[1];GLuint texBOTexture;GLuint windowTexture;GLfloat exposure;GLint sampleCount;GLint lastSampleCount;GLuint sampleWeightBuf;GLfloat sampleWeights[8][8];GLuint useWeightedResolve;void GenerateOrtho2DMat(GLuint imageWidth, GLuint imageHeight);bool LoadOpenEXRImage(char *fileName, GLint textureName, GLuint &texWidth, GLuint &texHeight);void SetupTexReplaceProg(GLfloat *vLightPos, GLfloat *vColor);void SetupFlatColorProg(GLfloat *vLightPos, GLfloat *vColor);void SetupHDRProg();///// Load in a BMP file as a texture. Allows specification of the filters and the wrap modebool LoadBMPTexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode){ GLbyte *pBits; GLint iWidth, iHeight; pBits = gltReadBMPBits(szFileName, &iWidth, &iHeight); if (pBits == NULL) return false; // Set Wrap modes glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); // Do I need to generate mipmaps? if (minFilter == GL_LINEAR_MIPMAP_LINEAR || minFilter == GL_LINEAR_MIPMAP_NEAREST || minFilter == GL_NEAREST_MIPMAP_LINEAR || minFilter == GL_NEAREST_MIPMAP_NEAREST) glGenerateMipmap(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, iWidth, iHeight, 0, GL_BGR, GL_UNSIGNED_BYTE, pBits); return true;}///// OpenGL related startup code is safe to put here. Load textures, etc.void SetupRC(void){ GLenum err = glewInit(); if (GLEW_OK != err) { /* Problem: glewInit failed, something is seriously wrong. */ fprintf(stderr, "Error: %s\n", glewGetErrorString(err)); } glEnable(GL_DEPTH_TEST); exposure = 1.0f; // Light Blue glClearColor(vSkyBlue[0], vSkyBlue[1], vSkyBlue[2], vSkyBlue[3]); // Load geometry GLfloat alpha = 0.25f; floorBatch.Begin(GL_TRIANGLE_FAN, 4, 1); floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha); floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f); floorBatch.Normal3f(0.0, 1.0f, 0.0f); floorBatch.Vertex3f(-20.0f, -0.41f, 20.0f); floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha); floorBatch.MultiTexCoord2f(0, 1.00f, 0.0f); floorBatch.Normal3f(0.0, 1.0f, 0.0f); floorBatch.Vertex3f(20.0f, -0.41f, 20.0f); floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha); floorBatch.MultiTexCoord2f(0, 1.00f, 1.00f); floorBatch.Normal3f(0.0, 1.0f, 0.0f); floorBatch.Vertex3f(20.0f, -0.41f, -20.0f); floorBatch.Color4f(0.0f, 1.0f, 0.0f, alpha); floorBatch.MultiTexCoord2f(0, 0.0f, 1.00f); floorBatch.Normal3f(0.0, 1.0f, 0.0f); floorBatch.Vertex3f(-20.0f, -0.41f, -20.0f); floorBatch.End(); windowBatch.Begin(GL_TRIANGLE_FAN, 4, 1); windowBatch.Color4f(1.0f, 0.0f, 0.0f, 1.0f); windowBatch.MultiTexCoord2f(0, 0.0f, 0.0f); windowBatch.Normal3f(0.0f, 1.0f, 0.0f); windowBatch.Vertex3f(-1.0f, 0.0f, 0.0f); windowBatch.Color4f(1.0f, 0.0f, 0.0f, 1.0f); windowBatch.MultiTexCoord2f(0, 1.0f, 0.0f); windowBatch.Normal3f(0.0f, 1.0f, 0.0f); windowBatch.Vertex3f(1.0f, 0.0f, 0.0f); windowBatch.Color4f(1.0f, 0.0f, 0.0f, 1.0f); windowBatch.MultiTexCoord2f(0, 1.0f, 1.0f); windowBatch.Normal3f(0.0f, 1.0f, 0.0f); windowBatch.Vertex3f(1.0f, 2.0f, 0.0f); windowBatch.Color4f(1.0f, 0.0f, 0.0f, 1.0f); windowBatch.MultiTexCoord2f(0, 0.0f, 1.0f); windowBatch.Normal3f(0.0f, 1.0f, 0.0f); windowBatch.Vertex3f(-1.0f, 2.0f, 0.0f); windowBatch.End(); const float width = 0.2f; windowBorderBatch.Begin(GL_TRIANGLE_STRIP, 13); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01f, width, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01f, 0.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01f, width, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01f, 0.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01 - width, 0.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01f, 2.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01 - width, 2.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(1.01f, 2.0 - width, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01f, 2.f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01f, 2.0 - width, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01 + width, 2.f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01f, 0.0f, 0.01f); windowBorderBatch.Normal3f(0.0f, 0.0f, 1.0f); windowBorderBatch.Vertex3f(-1.01 + width, 0.0f, 0.01f); windowBorderBatch.End(); const float gridWidth = (float)0.01; const int gridLineCount = 24; windowGridBatch.Begin(GL_TRIANGLES, gridLineCount * 2 * 6); // bottom horizontal for (int i = 0; i < gridLineCount; i++) { float offset = 2 * ((float)(i + 1) / (float)(gridLineCount + 1)); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(-1.0f, offset + gridWidth, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(-1.0f, offset - gridWidth, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(1.0f, offset - gridWidth, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(1.0f, offset - gridWidth, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(1.0f, offset + gridWidth, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(-1.0f, offset + gridWidth, 0.01f); } // Verticals for (int i = 0; i < gridLineCount; i++) { float offset = 2 * ((float)(i + 1) / (float)(gridLineCount + 1)) - 1.0; windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset + gridWidth, 0.0f, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset - gridWidth, 0.0f, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset - gridWidth, 2.0f, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset - gridWidth, 2.0f, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset + gridWidth, 2.0, 0.01f); windowGridBatch.Normal3f(0.0f, 0.0f, 1.0f); windowGridBatch.Vertex3f(offset + gridWidth, 0.0f, 0.01f); } windowGridBatch.End(); glGenTextures(1, textures); glBindTexture(GL_TEXTURE_2D, textures[0]); LoadBMPTexture("marble.bmp", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT); // Setup HDR render texture glGenTextures(1, hdrTextures); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, hdrTextures[0]); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB16F, screenWidth, screenHeight, GL_FALSE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Attach HDR texture to fbo // Create and bind an FBO glGenFramebuffers(1, hdrFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrFBO[0]); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hdrTextures[0], 0); // Create window texture glGenTextures(1, &windowTexture); glBindTexture(GL_TEXTURE_2D, windowTexture); GLuint texWidth = 0; GLuint texHeight = 0; // Load HDR image from EXR file LoadOpenEXRImage(const_cast
("window.exr"), windowTexture, texWidth, texHeight); // Load flat color shader flatColorProg = gltLoadShaderPairWithAttributes("basic.vs", "color.fs", 3, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoord0"); glBindFragDataLocation(flatColorProg, 0, "oColor"); glBindFragDataLocation(flatColorProg, 1, "oBright"); glLinkProgram(flatColorProg); // Load texture replace shader texReplaceProg = gltLoadShaderPairWithAttributes("basic.vs", "tex_replace.fs", 3, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoord0"); glBindFragDataLocation(texReplaceProg, 0, "oColor"); glBindFragDataLocation(texReplaceProg, 1, "oBright"); glLinkProgram(texReplaceProg); // Load bloom shader hdrResolve = gltLoadShaderPairWithAttributes("basic.vs", "hdr_exposure.fs", 3, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoord0"); glBindFragDataLocation(hdrResolve, 0, "oColor"); glLinkProgram(hdrResolve); // Uncomment the line below to get the correct behavior. floorBatch.Draw(); // Get the location of each multisample sample int sampleCount = 0; glGetIntegerv(GL_SAMPLES, &sampleCount); float positions[64]; // Enough for at least 32 samples for (int i = 0; i < sampleCount; i++) { glGetMultisamplefv(GL_SAMPLE_POSITION, i, &positions[i * 2]); } // Limit sample count to 8x //assert(sampleCount >= 8); sampleCount = 8; float invertedSampleDistances[8]; // The maxDist is used for doing the distance inversion // You could use the actual max dist a sample could be, but that // would mean that sample would receive a weighting of 0, use 1.0 instead. //float maxDist = sqrt(0.5*0.5*2); float maxDist = 1.0f; // calculate the distance of each sample from the center, // then invert it so that samples closer to the center recieve more weight for (int i = 0; i < 8; i++) { double xDist = positions[i * 2] - 0.5; double yDist = positions[i * 2 + 1] - 0.5; invertedSampleDistances[i] = maxDist - sqrt(xDist*xDist + yDist * yDist); } // zero out sample weights array for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { sampleWeights[i][j] = 0.0f; } } // First array is easy, 1 sample so that samples weight is 1 sampleWeights[0][0] = 1.0f; // Add up the distances to get the total used for calculating weights for (int i = 1; i < 8; i++) { float totalWeight = 0.0f; for (int j = 0; j <= i; j++) totalWeight += invertedSampleDistances[j]; // Invert to get the factor used for each sample, the sum of all sample weights is always 1.0 float perSampleFactor = 1 / totalWeight; for (int j = 0; j <= i; j++) sampleWeights[i][j] = invertedSampleDistances[j] * perSampleFactor; } // Setup a texture buffer object for holding the sample weights glGenBuffers(1, &sampleWeightBuf); glBindBuffer(GL_TEXTURE_BUFFER_ARB, sampleWeightBuf); glBufferData(GL_TEXTURE_BUFFER_ARB, sizeof(float) * 8, sampleWeights, GL_DYNAMIC_DRAW); glBindBuffer(GL_TEXTURE_BUFFER_ARB, 0); // Load the texBO into texture 1 glActiveTexture(GL_TEXTURE1); glGenTextures(1, &texBOTexture); glBindTexture(GL_TEXTURE_BUFFER_ARB, texBOTexture); glTexBufferARB(GL_TEXTURE_BUFFER_ARB, GL_R32F, sampleWeightBuf); glActiveTexture(GL_TEXTURE0); // Reset framebuffer binding glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);}// Take a file name/location and load an OpenEXR// Load the image into the "texture" texture object and pass back the texture sizes// bool LoadOpenEXRImage(char *fileName, GLint textureName, GLuint &texWidth, GLuint &texHeight){ // The OpenEXR uses exception handling to report errors or failures // Do all work in a try block to catch any thrown exceptions. try { Imf::Array2D
pixels; Imf::RgbaInputFile file(fileName); Imath::Box2i dw = file.dataWindow(); texWidth = dw.max.x - dw.min.x + 1; texHeight = dw.max.y - dw.min.y + 1; pixels.resizeErase(texHeight, texWidth); file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y * texWidth, 1, texWidth); file.readPixels(dw.min.y, dw.max.y); GLfloat* texels = (GLfloat*)malloc(texWidth * texHeight * 3 * sizeof(GLfloat)); GLfloat* pTex = texels; // Copy OpenEXR into local buffer for loading into a texture for (unsigned int v = 0; v < texHeight; v++) { for (unsigned int u = 0; u < texWidth; u++) { Imf::Rgba texel = pixels[texHeight - v - 1][u]; pTex[0] = texel.r; pTex[1] = texel.g; pTex[2] = texel.b; pTex += 3; } } // Bind texture, load image, set tex state glBindTexture(GL_TEXTURE_2D, textureName); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, texWidth, texHeight, 0, GL_RGB, GL_FLOAT, texels); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); free(texels); } catch (Iex::BaseExc & e) { std::cerr << e.what() << std::endl; // // Handle exception. // } return true;}///// Do your cleanup here. Free textures, display lists, buffer objects, etc.void ShutdownRC(void){ // Make sure default FBO is bound glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); // Cleanup textures for (int i = 0; i < 5; i++) { glActiveTexture(GL_TEXTURE0 + i); glBindTexture(GL_TEXTURE_2D, 0); } glDeleteTextures(1, textures); glDeleteTextures(1, hdrTextures); glDeleteTextures(1, &texBOTexture); glDeleteTextures(1, &windowTexture); // cleanup buffers glDeleteBuffers(1, &sampleWeightBuf); // Cleanup FBOs glDeleteFramebuffers(1, hdrFBO);}void SetupFlatColorProg(GLfloat *vLightPos, GLfloat *vColor){ glUseProgram(flatColorProg); // Set projection matrix glUniformMatrix4fv(glGetUniformLocation(flatColorProg, "pMatrix"), 1, GL_FALSE, transformPipeline.GetProjectionMatrix()); // Set MVP matrix glUniformMatrix4fv(glGetUniformLocation(flatColorProg, "mvMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewMatrix()); // Set Light Pos glUniform3fv(glGetUniformLocation(flatColorProg, "vLightPos"), 1, vLightPos); // Set Color glUniform4fv(glGetUniformLocation(flatColorProg, "vColor"), 1, vColor); gltCheckErrors(flatColorProg);}void SetupTexReplaceProg(GLfloat *vLightPos, GLfloat *vColor){ glUseProgram(texReplaceProg); // Set projection matrix glUniformMatrix4fv(glGetUniformLocation(texReplaceProg, "pMatrix"), 1, GL_FALSE, transformPipeline.GetProjectionMatrix()); // Set MVP matrix glUniformMatrix4fv(glGetUniformLocation(texReplaceProg, "mvMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewMatrix()); // Set Light Pos glUniform3fv(glGetUniformLocation(texReplaceProg, "vLightPos"), 1, vLightPos); // Set Color glUniform4fv(glGetUniformLocation(texReplaceProg, "vColor"), 1, vColor); // Set Tex Unit glUniform1i(glGetUniformLocation(texReplaceProg, "textureUnit0"), 0); gltCheckErrors(texReplaceProg);}void SetupHDRProg(){ glUseProgram(hdrResolve); // Set projection matrix glUniformMatrix4fv(glGetUniformLocation(hdrResolve, "pMatrix"), 1, GL_FALSE, transformPipeline.GetProjectionMatrix()); // Set MVP matrix glUniformMatrix4fv(glGetUniformLocation(hdrResolve, "mvMatrix"), 1, GL_FALSE, transformPipeline.GetModelViewMatrix()); // Set user controled uniforms glUniform1fv(glGetUniformLocation(hdrResolve, "exposure"), 1, &exposure); // Set texture uniforms glUniform1i(glGetUniformLocation(hdrResolve, "origImage"), 0); glUniform1i(glGetUniformLocation(hdrResolve, "sampleWeightSampler"), 1); // Setup MS sepcific uniforms glUniform1i(glGetUniformLocation(hdrResolve, "sampleCount"), sampleCount); glUniform1i(glGetUniformLocation(hdrResolve, "useWeightedResolve"), useWeightedResolve); // Now setup the right textures glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, hdrTextures[0]); // Check if sample weight buffer needs to be updated if (sampleCount != lastSampleCount) { glBindBuffer(GL_TEXTURE_BUFFER_ARB, sampleWeightBuf); void *data = glMapBufferRange(GL_TEXTURE_BUFFER_ARB, 0, sizeof(float) * 8, (GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT)); memcpy(data, (void*)sampleWeights[sampleCount], sizeof(float) * 8); glUnmapBuffer(GL_TEXTURE_BUFFER_ARB); lastSampleCount = sampleCount; } gltCheckErrors(hdrResolve);}///// This is called at least once and before any rendering occurs. If the screen// is a resizeable window, then this will also get called whenever the window// is resized.void ChangeSize(int nWidth, int nHeight){ glViewport(0, 0, nWidth, nHeight); transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix); viewFrustum.SetPerspective(35.0f, float(nWidth) / float(nHeight), 1.0f, 100.0f); projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix()); modelViewMatrix.LoadIdentity(); // update screen sizes screenWidth = nWidth; screenHeight = nHeight; glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, hdrTextures[0]); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGB16F, screenWidth, screenHeight, GL_FALSE); GenerateOrtho2DMat(nWidth, nHeight); glUseProgram(0);}///// Create a matrix that maps geometry to the screen. 1 unit in the x directionequals one pixel // of width, same with the y direction.//void GenerateOrtho2DMat(GLuint imageWidth, GLuint imageHeight){ float right = (float)imageWidth; float quadWidth = right; float left = 0.0f; float top = (float)imageHeight; float quadHeight = top; float bottom = 0.0f; // set ortho matrix orthoMatrix[0] = (float)(2 / (right)); orthoMatrix[1] = 0.0; orthoMatrix[2] = 0.0; orthoMatrix[3] = 0.0; orthoMatrix[4] = 0.0; orthoMatrix[5] = (float)(2 / (top)); orthoMatrix[6] = 0.0; orthoMatrix[7] = 0.0; orthoMatrix[8] = 0.0; orthoMatrix[9] = 0.0; orthoMatrix[10] = (float)(-2 / (1.0 - 0.0)); orthoMatrix[11] = 0.0; orthoMatrix[12] = -1.0f; orthoMatrix[13] = -1.0f; orthoMatrix[14] = -1.0f; orthoMatrix[15] = 1.0; // set screen quad vertex array screenQuad.Reset(); screenQuad.Begin(GL_TRIANGLE_STRIP, 4, 1); screenQuad.Color4f(0.0f, 1.0f, 0.0f, 1.0f); screenQuad.MultiTexCoord2f(0, 0.0f, 0.0f); screenQuad.Vertex3f(0.0f, 0.0f, 0.0f); screenQuad.Color4f(0.0f, 1.0f, 0.0f, 1.0f); screenQuad.MultiTexCoord2f(0, 1.0f, 0.0f); screenQuad.Vertex3f(right, 0.0f, 0.0f); screenQuad.Color4f(0.0f, 1.0f, 0.0f, 1.0f); screenQuad.MultiTexCoord2f(0, 0.0f, 1.0f); screenQuad.Vertex3f(0.0f, top, 0.0f); screenQuad.Color4f(0.0f, 1.0f, 0.0f, 1.0f); screenQuad.MultiTexCoord2f(0, 1.0f, 1.0f); screenQuad.Vertex3f(right, top, 0.0f); screenQuad.End();}///// Update the camera based on user input, toggle display modes// void SpecialKeys(int key, int x, int y){ static CStopWatch timer; float fTime = timer.GetElapsedSeconds(); float linear = fTime / 100; float smallLinear = fTime / 1000; // Increase the scene exposure if (key == GLUT_KEY_UP) { if ((exposure + smallLinear) < 20.0f) exposure += smallLinear; } // Decrease the scene exposure if (key == GLUT_KEY_DOWN) { if ((exposure - smallLinear) > 0.01f) exposure -= smallLinear; }}void ProcessKeys(unsigned char key, int x, int y){ if (key == 'q' || key == 'Q') { useWeightedResolve = 0; } if (key == 'w' || key == 'W') { useWeightedResolve = 1; } if (key == '1') sampleCount = 0; else if (key == '2') sampleCount = 1; else if (key == '3') sampleCount = 2; else if (key == '4') sampleCount = 3; else if (key == '5') sampleCount = 4; else if (key == '6') sampleCount = 5; else if (key == '7') sampleCount = 6; else if (key == '8') sampleCount = 7;}///// Render a frame. The owning framework is responsible for buffer swaps,// flushes, etc.void RenderScene(void){ // first render the scene in HDR to fbo glBindFramebuffer(GL_DRAW_FRAMEBUFFER, hdrFBO[0]); glDrawBuffers(1, &fboBuffs[0]); glClearColor(vSkyBlue[0], vSkyBlue[1], vSkyBlue[2], vSkyBlue[3]); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Draw to two textures, the first contains scene data // the second contains only the bright areas modelViewMatrix.PushMatrix(); M3DMatrix44f mCamera; cameraFrame.GetCameraMatrix(mCamera); modelViewMatrix.MultMatrix(mCamera); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); // Marble // Draw the floor SetupTexReplaceProg(vLightPos, vWhite); floorBatch.Draw(); // Draw the window modelViewMatrix.PushMatrix(); modelViewMatrix.Translate(0.0f, -0.4f, -4.0f); modelViewMatrix.Rotate(10.0, 0.0, 1.0, 0.0); glBindTexture(GL_TEXTURE_2D, windowTexture); // Window Tex // First draw the window contents from texture SetupTexReplaceProg(vLightPos, vWhiteX2); windowBatch.Draw(); // Now draw the border and the grid SetupFlatColorProg(vLightPos, vLtGrey); windowGridBatch.Draw(); windowBorderBatch.Draw(); modelViewMatrix.PopMatrix(); modelViewMatrix.PopMatrix(); projectionMatrix.PushMatrix(); projectionMatrix.LoadMatrix(orthoMatrix); modelViewMatrix.PushMatrix(); modelViewMatrix.LoadIdentity(); // Combine original scene with blurred bright textures // to create the bloom effect glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glDrawBuffers(1, windowBuff); glViewport(0, 0, screenWidth, screenHeight); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); SetupHDRProg(); screenQuad.Draw(); modelViewMatrix.PopMatrix(); projectionMatrix.PopMatrix(); // Put the texture units back the way they were glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); // Do the buffer Swap glutSwapBuffers(); // Do it again glutPostRedisplay();}int main(int argc, char* argv[]){ screenWidth = 800; screenHeight = 600; sampleCount = 0; useWeightedResolve = 1; gltSetWorkingDirectory(argv[0]); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(screenWidth, screenHeight); glutCreateWindow("HDR MSAA"); glutReshapeFunc(ChangeSize); glutDisplayFunc(RenderScene); glutSpecialFunc(SpecialKeys); glutKeyboardFunc(ProcessKeys); SetupRC(); glutMainLoop(); ShutdownRC(); return 0;}

 

上一篇:【OpenGL】蓝宝书第十章——片段操作:管线的终点
下一篇:【OpenGL】hdr_bloom 泛光示例程序

发表评论

最新留言

哈哈,博客排版真的漂亮呢~
[***.90.31.176]2025年04月23日 04时05分03秒