Пример #1
0
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);
}
Пример #2
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;
}
Пример #3
0
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;
}
Пример #4
0
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;
}
Пример #5
0
/**
 * 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);
}
Пример #6
0
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);
}