我有以下OpenGL / GLSL代码。我试图将两个纹理带入着色器并获得两个不同的纹理。
目前我只做无意义的计算。但对于我的实际应用(HDR成像),我需要在一个着色器中输入和输出两个+纹理。
我的问题出在int main()
我不知道如何在四边形上显示其中一个输出纹理。
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>
#include <stdio.h>
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"in vec3 color;"
"in vec2 texcoord;"
"out vec2 Texcoord;"
"out vec3 Color;"
"void main() {"
" Color = color;"
" Texcoord = texcoord;"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"in vec3 Color;"
"in vec2 Texcoord;"
"out vec4 outColor1;"
"out vec4 outColor2;"
"uniform sampler2D texLena;"
"uniform sampler2D texTex7;"
"void main() {"
" vec4 colLena = texture(texLena, Texcoord);"
" vec4 colTex7 = texture(texTex7, Texcoord);"
" outColor1 = mix(colLena, colTex7, 0.75) * vec4(Color, 1.0);"
" outColor2 = mix(colLena, colTex7, 0.25);"
"}";
void printShaderInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}
void printProgramInfoLog(GLuint obj)
{
int infologLength = 0;
int charsWritten = 0;
char *infoLog;
glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
printf("%s\n",infoLog);
free(infoLog);
}
}
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
int main()
{
if (glfwInit() != GL_TRUE)
{
fprintf(stderr, "Failed to initialize GLFW\n");
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL", glfwGetPrimaryMonitor(), NULL);
glfwMakeContextCurrent(window);
glfwSetKeyCallback(window, key_callback);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
fprintf(stderr, "Failed to initialize GLEW\n");
return -1;
}
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
GLfloat vertices[] = {
-0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint ebo;
glGenBuffers(1, &ebo);
GLuint elements[] = {
0, 1, 2,
2, 3, 0
};
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements), elements, GL_STATIC_DRAW);
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
printShaderInfoLog(vertexShader);
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
printShaderInfoLog(fragmentShader);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor1");
glBindFragDataLocation(shaderProgram, 1, "outColor2");
glLinkProgram(shaderProgram);
printProgramInfoLog(shaderProgram);
glUseProgram(shaderProgram);
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 7*sizeof(float), 0);
GLint colAttrib = glGetAttribLocation(shaderProgram, "color");
glEnableVertexAttribArray(colAttrib);
glVertexAttribPointer(colAttrib, 3, GL_FLOAT, GL_FALSE,
7*sizeof(float), (void*)(2*sizeof(float)));
GLint texAttrib = glGetAttribLocation(shaderProgram, "texcoord");
glEnableVertexAttribArray(texAttrib);
glVertexAttribPointer(texAttrib, 2, GL_FLOAT, GL_FALSE,
7*sizeof(float), (void*)(5*sizeof(float)));
GLuint textures[2];
glGenTextures(2, textures);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
cv::Mat image = cv::imread("lena.tiff");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0,
GL_BGR, GL_UNSIGNED_BYTE, image.data);
image.release();
glUniform1i(glGetUniformLocation(shaderProgram, "texLena"), 0);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
image = cv::imread("tex7.jpg");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0,
GL_BGR, GL_UNSIGNED_BYTE, image.data);
glUniform1i(glGetUniformLocation(shaderProgram, "texTex7"), 1);
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_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLuint frameBuffer;
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
GLuint texFront;
glGenTextures(1, &texFront);
glBindTexture(GL_TEXTURE_2D, texFront);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows,0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texFront, 0);
GLuint texBack;
glGenTextures(1, &texBack);
glBindTexture(GL_TEXTURE_2D, texBack);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows,0,
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, texBack, 0);
image.release();
GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
glDrawBuffers(2, bufs);
while(!glfwWindowShouldClose(window))
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// What should I be doing here?
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texFront);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteTextures(1, textures);
glDeleteTextures(1, &texFront);
glDeleteTextures(1, &texBack);
glDeleteFramebuffers(1, &frameBuffer);
glDeleteProgram(shaderProgram);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
glDeleteBuffers(1, &ebo);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
glfwTerminate();
return 0;
}
如何texFront
选择要显示的COLOR_ATTACHMENT0
(我的glDrawElements
)?
修改
当我尝试显示COLOR_ATTACHMENT0
COLOR_ATTACHMENT1
的部分内容,我得到了一个奇怪的结果
答案 0 :(得分:3)
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex1);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, tex2);
然后glUniform1i
将uniform sampler2D
指向纹理绑定点(0/1)。
正常阅读(即texture()/texelFetch()
(texture2D()
&lt; GL3)。
使用glFramebufferTexture2D
将多个纹理作为颜色附件附加,然后设置glDrawBuffers
。
绑定帧缓冲区。
绘制几何体,从片段着色器中写入数据。
使用&lt; GL3:
gl_FragData[*]
或&gt; = GL3:
glBindFragDataLocation
和out colour1, colour2
ARB_image_load_store
是另一种选择,但这里没有必要。
旁注:如果没有RMW危险,从绑定到当前FBO的纹理中读取possible and works。
或者:
绘制一个全屏多边形,并使用片段着色器绘制您想要的任何内容(即您刚刚使用FBO编写的纹理的直通)。这可以通过使用glViewport
剪切的单个非常大的三角形来完成(如果位在屏幕之外,则无关紧要。)
请注意,要将任何内容绘制到默认的帧缓冲区,请使用glBindFramebuffer(GL_FRAMEBUFFER, 0);
取消绑定任何当前绑定的FBO
更简单一点,将FBO的内容blit到默认的帧缓冲区。
https://www.opengl.org/sdk/docs/man3/xhtml/glBlitFramebuffer.xml
glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); //destination
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_LINEAR);