void piglit_init(int argc, char**argv) { GLuint tex; piglit_require_extension("GL_ARB_gpu_shader5"); glGenFramebuffers(1, &ms_fbo); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, 64, 64, GL_TRUE); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0); if (!piglit_check_gl_error(GL_NO_ERROR)) { printf("fbo setup failed.\n"); piglit_report_result(PIGLIT_SKIP); } /* Test quantity varies from -1 to +1 over 64 pixels -- * so moving 1px changes its value by 1/32. */ draw_prog = piglit_build_simple_program( "#version 150\n" "uniform vec2 sample_pos;\n" "in vec2 p;\n" "out vec2 test;\n" "out vec2 ref;\n" "void main() {\n" " gl_Position = vec4(p, 0, 1);\n" " test = p;\n" " ref = p;\n" " ref.xy += sample_pos / 32;\n" "}\n", "#version 150\n" "#extension GL_ARB_gpu_shader5: require\n" "const int sample_id = 0;\n" "in vec2 test;\n" "in vec2 ref;\n" "void main() {\n" " gl_FragColor = vec4(" GAIN " * abs(\n" " interpolateAtSample(test, sample_id) - ref), 0, 1);\n" "}\n"); if (!draw_prog) { printf("draw_prog compile/link failed\n"); piglit_report_result(PIGLIT_FAIL); } test_prog = piglit_build_simple_program( "#version 150\n" "in vec2 p;\n" "void main() {\n" " gl_Position = vec4(p, 0, 1);\n" "}\n", "#version 150\n" "uniform sampler2DMS s;\n" "void main() {\n" " vec4 temp = \n" " texelFetch(s, ivec2(gl_FragCoord.xy), 0) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 1) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 2) +\n" " texelFetch(s, ivec2(gl_FragCoord.xy), 3);\n" " gl_FragColor = vec4(temp.x, 1-temp.y, temp.z, temp.w);\n" "}\n"); if (!test_prog) { printf("test_prog compile/link failed\n"); piglit_report_result(PIGLIT_FAIL); } sample_pos_loc = glGetUniformLocation(draw_prog, "sample_pos"); glUseProgram(test_prog); glUniform1i(glGetUniformLocation(test_prog, "s"), 0); if (!piglit_check_gl_error(GL_NO_ERROR)) { printf("shader setup failed\n"); piglit_report_result(PIGLIT_SKIP); } glGenVertexArrays(1, &vao); glBindVertexArray(vao); glEnableVertexAttribArray(0); glGenBuffers(1, &bo); glBindBuffer(GL_ARRAY_BUFFER, bo); glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW); glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (GLvoid const *)0); }
bool GBuffer::initialize( const Viewport& vp, bool multisample, int samples ) { int width =vp.width - vp.x; int height =vp.height - vp.y; /* First time initialize? */ if( !m_fbo ) { glEnable( GL_MULTISAMPLE ); glGenFramebuffers(1, &m_fbo); } else { glDeleteTextures( NUM_TEXTURES, m_textures); } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); // glRenderbufferStorageMultisample( GL_RENDERBUFFER, 2, GL_DEPTH24_STENCIL8, width, height ); glGenTextures( NUM_TEXTURES, m_textures ); /* Depth */ if( multisample ) { glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, m_textures[DEPTH_TEXTURE] ); glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, samples, GL_DEPTH_COMPONENT32F, width, height, false ); /* glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_LUMINANCE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);*/ glFramebufferTexture2D( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, m_textures[DEPTH_TEXTURE], 0 ); } else { glBindTexture(GL_TEXTURE_2D, m_textures[DEPTH_TEXTURE]); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[DEPTH_TEXTURE], 0); } /* Diffuse + spec */ if( multisample ) { glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, m_textures[DIFFUSE_SPEC_TEXTURE] ); glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA16F, width, height, false ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, m_textures[DIFFUSE_SPEC_TEXTURE], 0 ); } else { glBindTexture(GL_TEXTURE_2D, m_textures[DIFFUSE_SPEC_TEXTURE]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[DIFFUSE_SPEC_TEXTURE], 0); } /* printf("GL error, status: 0x%x\n", glGetError());*/ /* Normals */ if( multisample ) { glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, m_textures[NORMAL_TEXTURE] ); glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB16F, width, height, false ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, m_textures[NORMAL_TEXTURE], 0 ); } else { glBindTexture(GL_TEXTURE_2D, m_textures[NORMAL_TEXTURE]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, width, height, 0, GL_RGB, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_textures[NORMAL_TEXTURE], 0); } /* Position */ if( multisample ) { glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, m_textures[POSITION_TEXTURE] ); glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA16F, width, height, false ); glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D_MULTISAMPLE, m_textures[POSITION_TEXTURE], 0 ); } else { glBindTexture(GL_TEXTURE_2D, m_textures[POSITION_TEXTURE]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, m_textures[POSITION_TEXTURE], 0); } GLenum DrawBuffers[] = { /*GL_DEPTH_ATTACHMENT, */GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2/*, GL_COLOR_ATTACHMENT3 */}; glDrawBuffers(NUM_TEXTURES-1, DrawBuffers); GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER); if (Status != GL_FRAMEBUFFER_COMPLETE) { printf("FB error, status: 0x%x\n", Status); return false; } m_width =width; m_height =height; m_multisample =multisample; glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); return true; }
GLUSboolean init(GLUSvoid) { GLUSshape backgroundSphere; GLUSshape wavefront; // 6 sides of diffuse and specular; all roughness levels of specular. GLUShdrimage image[6 * NUMBER_ROUGHNESS + 6]; // The look up table (LUT) is stored in a raw binary file. GLUSbinaryfile rawimage; GLUStextfile vertexSource; GLUStextfile fragmentSource; GLchar buffer[27] = "doge2/doge2_POS_X_00_s.hdr"; GLint i, k, m; // glusLoadTextFile("../Example33/shader/brdf.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/brdf.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_modelProgram, (const GLchar**)&vertexSource.text, 0, 0, 0, (const GLchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); g_viewProjectionMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_viewProjectionMatrix"); g_modelMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_modelMatrix"); g_normalMatrixModelLocation = glGetUniformLocation(g_modelProgram.program, "u_normalMatrix"); g_eyeModelLocation = glGetUniformLocation(g_modelProgram.program, "u_eye"); g_textureSpecularModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureSpecular"); g_textureDiffuseModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureDiffuse"); g_textureLUTModelLocation = glGetUniformLocation(g_modelProgram.program, "u_textureLUT"); g_colorMaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_colorMaterial"); g_roughnessMaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_roughnessMaterial"); g_roughnessScaleModelLocation = glGetUniformLocation(g_modelProgram.program, "u_roughnessScale"); g_R0MaterialModelLocation = glGetUniformLocation(g_modelProgram.program, "u_R0Material"); g_vertexModelLocation = glGetAttribLocation(g_modelProgram.program, "a_vertex"); g_normalModelLocation = glGetAttribLocation(g_modelProgram.program, "a_normal"); // glusLoadTextFile("../Example33/shader/fullscreen.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/fullscreen.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_fullscreenProgram, (const GLchar**)&vertexSource.text, 0, 0, 0, (const GLchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // g_framebufferTextureFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_framebufferTexture"); g_msaaSamplesFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_msaaSamples"); g_exposureFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_exposure"); g_gammaFullscreenLocation = glGetUniformLocation(g_fullscreenProgram.program, "u_gamma"); // // glusLoadTextFile("../Example33/shader/background.vert.glsl", &vertexSource); glusLoadTextFile("../Example33/shader/background.frag.glsl", &fragmentSource); glusBuildProgramFromSource(&g_backgroundProgram, (const GLUSchar**)&vertexSource.text, 0, 0, 0, (const GLUSchar**)&fragmentSource.text); glusDestroyTextFile(&vertexSource); glusDestroyTextFile(&fragmentSource); // g_viewProjectionMatrixBackgroundLocation = glGetUniformLocation(g_backgroundProgram.program, "u_viewProjectionMatrix"); g_textureBackgroundLocation = glGetUniformLocation(g_backgroundProgram.program, "u_texture"); g_vertexBackgroundLocation = glGetAttribLocation(g_backgroundProgram.program, "a_vertex"); // // Setting up the full screen frame buffer. // glGenTextures(1, &g_fullscreenTexture); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, g_fullscreenTexture); // Create MSAA texture. glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, MSAA_SAMPLES, GL_RGB32F, SCREEN_WIDTH, SCREEN_HEIGHT, GL_TRUE); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0); // No need to access the depth buffer, so a render buffer is sufficient. glGenRenderbuffers(1, &g_fullscreenDepthRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, g_fullscreenDepthRenderbuffer); glRenderbufferStorageMultisample(GL_RENDERBUFFER, MSAA_SAMPLES, GL_DEPTH_COMPONENT, SCREEN_WIDTH, SCREEN_HEIGHT); glBindRenderbuffer(GL_RENDERBUFFER, 0); // glGenFramebuffers(1, &g_fullscreenFBO); glBindFramebuffer(GL_FRAMEBUFFER, g_fullscreenFBO); // Attach the color buffer ... glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, g_fullscreenTexture, 0); // ... and the depth buffer. glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_fullscreenDepthRenderbuffer); if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { printf("GL_FRAMEBUFFER_COMPLETE error 0x%x", glCheckFramebufferStatus(GL_FRAMEBUFFER)); return GLUS_FALSE; } glBindFramebuffer(GL_FRAMEBUFFER, 0); // // // for (i = 0; i < 2; i++) { if (i == 0) { buffer[21] = 's'; } else { buffer[21] = 'd'; } for (k = 0; k < NUMBER_ROUGHNESS; k++) { if (i == 1 && k > 0) { continue; } buffer[18] = '0' + k / 10; buffer[19] = '0' + k % 10; for (m = 0; m < 6; m++) { if (m % 2 == 0) { buffer[12] = 'P'; buffer[13] = 'O'; buffer[14] = 'S'; } else { buffer[12] = 'N'; buffer[13] = 'E'; buffer[14] = 'G'; } switch (m) { case 0: case 1: buffer[16] = 'X'; break; case 2: case 3: buffer[16] = 'Y'; break; case 4: case 5: buffer[16] = 'Z'; break; } printf("Loading '%s' ...", buffer); if (!glusLoadHdrImage(buffer, &image[i*NUMBER_ROUGHNESS*6 + k*6 + m])) { printf(" error!\n"); continue; } printf(" done.\n"); } } } glGenTextures(1, &g_texture[0]); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, g_texture[0]); glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGB32F, image[0].width, image[0].height, 6*NUMBER_ROUGHNESS, 0, GL_RGB, GL_FLOAT, 0); glusLogPrintError(GLUS_LOG_INFO, "glTexImage3D()"); for (i = 0; i < NUMBER_ROUGHNESS; i++) { for (k = 0; k < 6; k++) { glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, 0, 6*i + k, image[i*6 + k].width, image[i*6 + k].height, 1, image[i*6 + k].format, GL_FLOAT, image[i*6 + k].data); glusLogPrintError(GLUS_LOG_INFO, "glTexSubImage3D() %d %d", i, k); } } glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); // glGenTextures(1, &g_texture[1]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_CUBE_MAP, g_texture[1]); for (i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, image[i + 6*NUMBER_ROUGHNESS].format, image[i + 6*NUMBER_ROUGHNESS].width, image[i + 6*NUMBER_ROUGHNESS].height, 0, image[i + 6*NUMBER_ROUGHNESS].format, GL_FLOAT, image[i + 6*NUMBER_ROUGHNESS].data); glusLogPrintError(GLUS_LOG_INFO, "glTexImage2D() %d", i); } glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_CUBE_MAP, 0); // printf("Loading 'doge2/EnvironmentBRDF_1024.data' ..."); if (!glusLoadBinaryFile("doge2/EnvironmentBRDF_1024.data", &rawimage)) { printf(" error!\n"); } else { printf(" done.\n"); } glGenTextures(1, &g_texture[2]); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, g_texture[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F, 1024, 1024, 0, GL_RG, GL_FLOAT, (GLfloat*)rawimage.binary); glusLogPrintError(GLUS_LOG_INFO, "glTexImage2D()"); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(GL_TEXTURE_2D, 0); glusDestroyBinaryFile(&rawimage); // for (i = 0; i < 2; i++) { for (k = 0; k < NUMBER_ROUGHNESS; k++) { if (i == 1 && k > 0) { continue; } for (m = 0; m < 6; m++) { glusDestroyHdrImage(&image[i*NUMBER_ROUGHNESS*6 + k*6 + m]); } } } // glusCreateSpheref(&backgroundSphere, 500.0f, 32); g_numberIndicesBackground = backgroundSphere.numberIndices; glGenBuffers(1, &g_verticesBackgroundVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesBackgroundVBO); glBufferData(GL_ARRAY_BUFFER, backgroundSphere.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)backgroundSphere.vertices, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glGenBuffers(1, &g_indicesBackgroundVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesBackgroundVBO); glBufferData(GL_ELEMENT_ARRAY_BUFFER, backgroundSphere.numberIndices * sizeof(GLuint), (GLuint*)backgroundSphere.indices, GL_STATIC_DRAW); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glusDestroyShapef(&backgroundSphere); // // // Use a helper function to load an wavefront object file. glusLoadObjFile("venusm.obj", &wavefront); g_numberVerticesModel = wavefront.numberVertices; glGenBuffers(1, &g_verticesModelVBO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesModelVBO); glBufferData(GL_ARRAY_BUFFER, wavefront.numberVertices * 4 * sizeof(GLfloat), (GLfloat*)wavefront.vertices, GL_STATIC_DRAW); glGenBuffers(1, &g_normalsModelVBO); glBindBuffer(GL_ARRAY_BUFFER, g_normalsModelVBO); glBufferData(GL_ARRAY_BUFFER, wavefront.numberVertices * 3 * sizeof(GLfloat), (GLfloat*)wavefront.normals, GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); glusDestroyShapef(&wavefront); // glUseProgram(g_modelProgram.program); glUniform4fv(g_eyeModelLocation, 1, g_eye); glUniform1i(g_textureSpecularModelLocation, 0); glUniform1i(g_textureDiffuseModelLocation, 1); glUniform1i(g_textureLUTModelLocation, 2); glUniform1f(g_roughnessScaleModelLocation, (GLfloat)(NUMBER_ROUGHNESS - 1)); glGenVertexArrays(1, &g_modelVAO); glBindVertexArray(g_modelVAO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesModelVBO); glVertexAttribPointer(g_vertexModelLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexModelLocation); glBindBuffer(GL_ARRAY_BUFFER, g_normalsModelVBO); glVertexAttribPointer(g_normalModelLocation, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_normalModelLocation); // glUseProgram(g_fullscreenProgram.program); glUniform1i(g_framebufferTextureFullscreenLocation, 0); glUniform1i(g_msaaSamplesFullscreenLocation, MSAA_SAMPLES); glGenVertexArrays(1, &g_fullscreenVAO); glBindVertexArray(g_fullscreenVAO); // glUseProgram(g_backgroundProgram.program); glUniform1i(g_textureBackgroundLocation, 0); glGenVertexArrays(1, &g_backgroundVAO); glBindVertexArray(g_backgroundVAO); glBindBuffer(GL_ARRAY_BUFFER, g_verticesBackgroundVBO); glVertexAttribPointer(g_vertexBackgroundLocation, 4, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(g_vertexBackgroundLocation); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_indicesBackgroundVBO); // glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClearDepth(1.0f); glEnable(GL_CULL_FACE); return GLUS_TRUE; }
static GPUTexture *GPU_texture_create_nD( int w, int h, int n, const float *fpixels, int depth, GPUHDRType hdr_type, int components, int samples, char err_out[256]) { GLenum type, format, internalformat; void *pixels = NULL; if (samples) { CLAMP_MAX(samples, GPU_max_color_texture_samples()); } GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->number = -1; tex->refcount = 1; tex->target = (n == 1) ? GL_TEXTURE_1D : (samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); tex->target_base = (n == 1) ? GL_TEXTURE_1D : GL_TEXTURE_2D; tex->depth = depth; tex->fb_attachment = -1; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { if (err_out) { BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", (int)glGetError()); } else { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); } GPU_texture_free(tex); return NULL; } if (!GPU_full_non_power_of_two_support()) { tex->w = power_of_2_max_i(tex->w); tex->h = power_of_2_max_i(tex->h); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); if (depth) { type = GL_UNSIGNED_BYTE; format = GL_DEPTH_COMPONENT; internalformat = GL_DEPTH_COMPONENT; } else { type = GL_FLOAT; if (components == 4) { format = GL_RGBA; switch (hdr_type) { case GPU_HDR_NONE: internalformat = GL_RGBA8; break; /* the following formats rely on ARB_texture_float or OpenGL 3.0 */ case GPU_HDR_HALF_FLOAT: internalformat = GL_RGBA16F_ARB; break; case GPU_HDR_FULL_FLOAT: internalformat = GL_RGBA32F_ARB; break; default: break; } } else if (components == 2) { /* these formats rely on ARB_texture_rg or OpenGL 3.0 */ format = GL_RG; switch (hdr_type) { case GPU_HDR_NONE: internalformat = GL_RG8; break; case GPU_HDR_HALF_FLOAT: internalformat = GL_RG16F; break; case GPU_HDR_FULL_FLOAT: internalformat = GL_RG32F; break; default: break; } } if (fpixels && hdr_type == GPU_HDR_NONE) { type = GL_UNSIGNED_BYTE; pixels = GPU_texture_convert_pixels(w * h, fpixels); } } if (tex->target == GL_TEXTURE_1D) { glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); if (fpixels) { glTexSubImage1D(tex->target, 0, 0, w, format, type, pixels ? pixels : fpixels); if (tex->w > w) { GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, 1); } } } else { if (samples) { glTexImage2DMultisample(tex->target, samples, internalformat, tex->w, tex->h, true); } else { glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, type, NULL); } if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels ? pixels : fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w - w, tex->h); if (tex->h > h) GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h - h); } } if (pixels) MEM_freeN(pixels); if (depth) { glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); glTexParameteri(tex->target_base, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY); } else { glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (tex->target_base != GL_TEXTURE_1D) { glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } else glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return tex; }
/** * This function does any needed initialization on the rendering context. * This is the first opportunity to do any OpenGL related tasks. */ void SetupRC() { // Blue background glClearColor(0.0f, 0.0f, 1.0f, 1.0f ); shaderManager.init(); glEnable(GL_DEPTH_TEST); gltCreateCylinder(bckgrndCylBatch, 4.0f, 4.0f, 5.2f, 1024, 1); gltCreateDisk(diskBatch, 0.0f, 1.5f, 40, 10); glass1Batch.begin(GL_TRIANGLE_FAN, 4, 1); glass1Batch.Vertex3f(-1.0f, -1.0f, 0.0f); glass1Batch.Vertex3f(1.0f, -1.0f, 0.0f); glass1Batch.Vertex3f(1.0f, 1.0f, 0.0f); glass1Batch.Vertex3f(-1.0f, 1.0f, 0.0f); glass1Batch.end(); glass2Batch.begin(GL_TRIANGLE_FAN, 4, 1); glass2Batch.Vertex3f(0.0f, 1.0f, 0.0f); glass2Batch.Vertex3f(1.0f, 0.0f, 0.0f); glass2Batch.Vertex3f(0.0f, -1.0f, 0.0f); glass2Batch.Vertex3f(-1.0f, 0.0f, 0.0f); glass2Batch.end(); glass3Batch.begin(GL_TRIANGLE_FAN, 3, 1); glass3Batch.Vertex3f(0.0f, 1.0f, 0.0f); glass3Batch.Vertex3f(1.0f, -1.0f, 0.0f); glass3Batch.Vertex3f(-1.0f, -1.0f, 0.0f); glass3Batch.end(); glass4Batch.begin(GL_TRIANGLE_FAN, 4, 1); glass4Batch.Vertex3f(-1.0f, 1.0f, 0.0f); glass4Batch.Vertex3f(1.0f, 0.5f, 0.0f); glass4Batch.Vertex3f(1.0f, -1.0f, 0.0f); glass4Batch.Vertex3f(-1.0f, -0.5f, 0.0f); glass4Batch.end(); glGenTextures(2, textures); glBindTexture(GL_TEXTURE_2D, textures[0]); gltLoadTextureBMP("marble.bmp", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT); glBindTexture(GL_TEXTURE_2D, textures[1]); gltLoadTextureBMP("start_line.bmp", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_REPEAT); // create and bind an FBO glGenFramebuffers(1, &msFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msFBO); // create depth texture glGenTextures(1, &depthTextureName); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, depthTextureName); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_DEPTH_COMPONENT24, screenWidth, screenHeight, GL_FALSE); // setup HDR render texture glGenTextures(1, msTexture); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, msTexture[0]); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 8, GL_RGBA8, screenWidth, screenHeight, GL_FALSE); // create and bind FBO glGenFramebuffers(1, &msFBO); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, msFBO); // attach texture to first color attachment and depth RBO glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, msTexture[0], 0); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D_MULTISAMPLE, depthTextureName, 0); // reset framebuffer binding glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Load oit resolve shader oitResolve = gltLoadShaderWithFileEx("basic.vs", "oitResolve.fs", 3, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoord0"); glBindFragDataLocation(oitResolve, 0, "oColor"); glLinkProgram(oitResolve); // Load multisample resolve shader msResolve = gltLoadShaderWithFileEx("basic.vs", "msResolve.fs", 3, GLT_ATTRIBUTE_VERTEX, "vVertex", GLT_ATTRIBUTE_NORMAL, "vNormal", GLT_ATTRIBUTE_TEXTURE0, "vTexCoord0"); glBindFragDataLocation(msResolve, 0, "oColor"); glLinkProgram(msResolve); // Make sure all went well gltCheckErrors(oitResolve); gltCheckErrors(msResolve); int numMasks = 0; glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &numMasks); log("GL_MAX_SAMPLE_MASK_WORDS: %d", numMasks); }
FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int msaaSamples) { m_xfbFramebuffer = 0; m_efbColor = 0; m_efbDepth = 0; m_efbColorSwap = 0; m_resolvedColorTexture = 0; m_resolvedDepthTexture = 0; m_targetWidth = targetWidth; m_targetHeight = targetHeight; m_msaaSamples = msaaSamples; // The EFB can be set to different pixel formats by the game through the // BPMEM_ZCOMPARE register (which should probably have a different name). // They are: // - 24-bit RGB (8-bit components) with 24-bit Z // - 24-bit RGBA (6-bit components) with 24-bit Z // - Multisampled 16-bit RGB (5-6-5 format) with 16-bit Z // We only use one EFB format here: 32-bit ARGB with 24-bit Z. // Multisampling depends on user settings. // The distinction becomes important for certain operations, i.e. the // alpha channel should be ignored if the EFB does not have one. glActiveTexture(GL_TEXTURE9); GLuint glObj[3]; glGenTextures(3, glObj); m_efbColor = glObj[0]; m_efbDepth = glObj[1]; m_efbColorSwap = glObj[2]; m_EFBLayers = (g_ActiveConfig.iStereoMode > 0) ? 2 : 1; m_efbFramebuffer.resize(m_EFBLayers); m_resolvedFramebuffer.resize(m_EFBLayers); // OpenGL MSAA textures are a different kind of texture type and must be allocated // with a different function, so we create them separately. if (m_msaaSamples <= 1) { m_textureType = GL_TEXTURE_2D_ARRAY; glBindTexture(m_textureType, m_efbColor); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(m_textureType, m_efbDepth); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); glBindTexture(m_textureType, m_efbColorSwap); glTexParameteri(m_textureType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(m_textureType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } else { GLenum resolvedType = GL_TEXTURE_2D_ARRAY; // Only use a layered multisample texture if needed. Some drivers // slow down significantly with single-layered multisample textures. if (m_EFBLayers > 1) { m_textureType = GL_TEXTURE_2D_MULTISAMPLE_ARRAY; if (g_ogl_config.bSupports3DTextureStorage) { glBindTexture(m_textureType, m_efbColor); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbDepth); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbColorSwap); glTexStorage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, 0); } else { glBindTexture(m_textureType, m_efbColor); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbDepth); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, m_efbColorSwap); glTexImage3DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, false); glBindTexture(m_textureType, 0); } } else { m_textureType = GL_TEXTURE_2D_MULTISAMPLE; if (g_ogl_config.bSupports2DTextureStorage) { glBindTexture(m_textureType, m_efbColor); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbDepth); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbColorSwap); glTexStorage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA8, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, 0); } else { glBindTexture(m_textureType, m_efbColor); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbDepth); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, m_efbColorSwap); glTexImage2DMultisample(m_textureType, m_msaaSamples, GL_RGBA, m_targetWidth, m_targetHeight, false); glBindTexture(m_textureType, 0); } } // Although we are able to access the multisampled texture directly, we don't do it everywhere. // The old way is to "resolve" this multisampled texture by copying it into a non-sampled texture. // This would lead to an unneeded copy of the EFB, so we are going to avoid it. // But as this job isn't done right now, we do need that texture for resolving: glGenTextures(2, glObj); m_resolvedColorTexture = glObj[0]; m_resolvedDepthTexture = glObj[1]; glBindTexture(resolvedType, m_resolvedColorTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(resolvedType, 0, GL_RGBA, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glBindTexture(resolvedType, m_resolvedDepthTexture); glTexParameteri(resolvedType, GL_TEXTURE_MAX_LEVEL, 0); glTexImage3D(resolvedType, 0, GL_DEPTH_COMPONENT32F, m_targetWidth, m_targetHeight, m_EFBLayers, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr); // Bind resolved textures to resolved framebuffer. glGenFramebuffers(m_EFBLayers, m_resolvedFramebuffer.data()); glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[0]); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, resolvedType, m_resolvedColorTexture, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, resolvedType, m_resolvedDepthTexture, 0); // Bind all the other layers as separate FBOs for blitting. for (unsigned int i = 1; i < m_EFBLayers; i++) { glBindFramebuffer(GL_FRAMEBUFFER, m_resolvedFramebuffer[i]); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_resolvedColorTexture, 0, i); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_resolvedDepthTexture, 0, i); } } // Create XFB framebuffer; targets will be created elsewhere. glGenFramebuffers(1, &m_xfbFramebuffer); // Bind target textures to EFB framebuffer. glGenFramebuffers(m_EFBLayers, m_efbFramebuffer.data()); glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[0]); FramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_textureType, m_efbColor, 0); FramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_textureType, m_efbDepth, 0); // Bind all the other layers as separate FBOs for blitting. for (unsigned int i = 1; i < m_EFBLayers; i++) { glBindFramebuffer(GL_FRAMEBUFFER, m_efbFramebuffer[i]); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_efbColor, 0, i); glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_efbDepth, 0, i); } // EFB framebuffer is currently bound, make sure to clear its alpha value to 1.f glViewport(0, 0, m_targetWidth, m_targetHeight); glScissor(0, 0, m_targetWidth, m_targetHeight); glClearColor(0.f, 0.f, 0.f, 1.f); glClearDepthf(1.0f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // reinterpret pixel format const char* vs = m_EFBLayers > 1 ? "void main(void) {\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" "}\n" : "flat out int layer;\n" "void main(void) {\n" " layer = 0;\n" " vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n" " gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n" "}\n"; // The way to sample the EFB is based on the on the current configuration. // As we use the same sampling way for both interpreting shaders, the sampling // shader are generated first: std::string sampler; if (m_msaaSamples <= 1) { // non-msaa, so just fetch the pixel sampler = "SAMPLER_BINDING(9) uniform sampler2DArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos, 0);\n" "}\n"; } else if (g_ActiveConfig.backend_info.bSupportsSSAA) { // msaa + sample shading available, so just fetch the sample // This will lead to sample shading, but it's the only way to not loose // the values of each sample. if (m_EFBLayers > 1) { sampler = "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos, gl_SampleID);\n" "}\n"; } else { sampler = "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " return texelFetch(samp9, pos.xy, gl_SampleID);\n" "}\n"; } } else { // msaa without sample shading: calculate the mean value of the pixel std::stringstream samples; samples << m_msaaSamples; if (m_EFBLayers > 1) { sampler = "SAMPLER_BINDING(9) uniform sampler2DMSArray samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n" " for(int i=0; i<" + samples.str() + "; i++)\n" " color += texelFetch(samp9, pos, 0), i);\n" " return color / " + samples.str() + ";\n" "}\n"; } else { sampler = "SAMPLER_BINDING(9) uniform sampler2DMS samp9;\n" "vec4 sampleEFB(ivec3 pos) {\n" " vec4 color = vec4(0.0, 0.0, 0.0, 0.0);\n" " for(int i=0; i<" + samples.str() + "; i++)\n" " color += texelFetch(samp9, pos.xy, i);\n" " return color / " + samples.str() + ";\n" "}\n"; } } std::string ps_rgba6_to_rgb8 = sampler + "flat in int layer;\n" "out vec4 ocol0;\n" "void main()\n" "{\n" " ivec4 src6 = ivec4(round(sampleEFB(ivec3(gl_FragCoord.xy, layer)) * 63.f));\n" " ivec4 dst8;\n" " dst8.r = (src6.r << 2) | (src6.g >> 4);\n" " dst8.g = ((src6.g & 0xF) << 4) | (src6.b >> 2);\n" " dst8.b = ((src6.b & 0x3) << 6) | src6.a;\n" " dst8.a = 255;\n" " ocol0 = float4(dst8) / 255.f;\n" "}"; std::string ps_rgb8_to_rgba6 = sampler + "flat in int layer;\n" "out vec4 ocol0;\n" "void main()\n" "{\n" " ivec4 src8 = ivec4(round(sampleEFB(ivec3(gl_FragCoord.xy, layer)) * 255.f));\n" " ivec4 dst6;\n" " dst6.r = src8.r >> 2;\n" " dst6.g = ((src8.r & 0x3) << 4) | (src8.g >> 4);\n" " dst6.b = ((src8.g & 0xF) << 2) | (src8.b >> 6);\n" " dst6.a = src8.b & 0x3F;\n" " ocol0 = float4(dst6) / 63.f;\n" "}"; std::stringstream vertices, layers; vertices << m_EFBLayers * 3; layers << m_EFBLayers; std::string gs = "layout(triangles) in;\n" "layout(triangle_strip, max_vertices = " + vertices.str() + ") out;\n" "flat out int layer;\n" "void main()\n" "{\n" " for (int j = 0; j < " + layers.str() + "; ++j) {\n" " for (int i = 0; i < 3; ++i) {\n" " layer = j;\n" " gl_Layer = j;\n" " gl_Position = gl_in[i].gl_Position;\n" " EmitVertex();\n" " }\n" " EndPrimitive();\n" " }\n" "}\n"; ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6.c_str(), (m_EFBLayers > 1) ? gs : ""); ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8.c_str(), (m_EFBLayers > 1) ? gs : ""); ProgramShaderCache::CompileShader(m_EfbPokes, StringFromFormat( "in vec2 rawpos;\n" "in vec4 color0;\n" // color "in int color1;\n" // depth "out vec4 v_c;\n" "out float v_z;\n" "void main(void) {\n" " gl_Position = vec4(((rawpos + 0.5) / vec2(640.0, 528.0) * 2.0 - 1.0) * vec2(1.0, -1.0), 0.0, 1.0);\n" " gl_PointSize = %d.0 / 640.0;\n" " v_c = color0.bgra;\n" " v_z = float(color1 & 0xFFFFFF) / 16777216.0;\n" "}\n", m_targetWidth), StringFromFormat( "in vec4 %s_c;\n" "in float %s_z;\n" "out vec4 ocol0;\n" "void main(void) {\n" " ocol0 = %s_c;\n" " gl_FragDepth = %s_z;\n" "}\n", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v", m_EFBLayers > 1 ? "g" : "v"), m_EFBLayers > 1 ? StringFromFormat( "layout(points) in;\n" "layout(points, max_vertices = %d) out;\n" "in vec4 v_c[1];\n" "in float v_z[1];\n" "out vec4 g_c;\n" "out float g_z;\n" "void main()\n" "{\n" " for (int j = 0; j < %d; ++j) {\n" " gl_Layer = j;\n" " gl_Position = gl_in[0].gl_Position;\n" " gl_PointSize = %d.0 / 640.0;\n" " g_c = v_c[0];\n" " g_z = v_z[0];\n" " EmitVertex();\n" " EndPrimitive();\n" " }\n" "}\n", m_EFBLayers, m_EFBLayers, m_targetWidth) : ""); glGenBuffers(1, &m_EfbPokes_VBO); glGenVertexArrays(1, &m_EfbPokes_VAO); glBindBuffer(GL_ARRAY_BUFFER, m_EfbPokes_VBO); glBindVertexArray(m_EfbPokes_VAO ); glEnableVertexAttribArray(SHADER_POSITION_ATTRIB); glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_UNSIGNED_SHORT, 0, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, x)); glEnableVertexAttribArray(SHADER_COLOR0_ATTRIB); glVertexAttribPointer(SHADER_COLOR0_ATTRIB, 4, GL_UNSIGNED_BYTE, 1, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, data)); glEnableVertexAttribArray(SHADER_COLOR1_ATTRIB); glVertexAttribIPointer(SHADER_COLOR1_ATTRIB, 1, GL_INT, sizeof(EfbPokeData), (void*)offsetof(EfbPokeData, data)); if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) glEnable(GL_PROGRAM_POINT_SIZE); }