2017-12-18 212 views
0

我无法通过统一的sampler2Ds发送两个纹理到我的片段着色器。我的片段着色器有两个制服,但看起来我的代码将同一图像发送给两个采样器。首先绑定的纹理似乎自动绑定到两个制服。OpenGL这两个统一的sampler2Ds具有相同的图像

完整C++代码如下:

#define GLEW_STATIC 
#include <GL/glew.h> 
#include <GLFW/glfw3.h> 
#include <glm/glm.hpp> 
#include <glm/gtc/matrix_transform.hpp> 
#include <glm/gtc/type_ptr.hpp> 
#include <SOIL/SOIL.h> 
#include <fstream> 
#include <iostream> 
#include <sstream> 
#include <string> 


int main(int argc, const char* argv[]) 
{ 
GLFWwindow* display; 
glfwInit(); 

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); 

display = glfwCreateWindow(1280, 720, "Game Engine", nullptr, nullptr); 
glfwMakeContextCurrent(display); 
glewExperimental = GL_TRUE; 
GLenum success = glewInit(); 

GLint height, width; 
glfwGetFramebufferSize(display, &width, &height); 
glViewport(0, 0, width, height); 
glEnable(GL_DEPTH_TEST); 

GLuint program; 
std::string vertexCode, fragmentCode; 
std::ifstream vShaderFile, fShaderFile; 

std::string vertexPath = "Basic.vert"; 
std::string fragmentPath = "Basic.frag"; 

vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit); 
try 
{ 
    vShaderFile.open(vertexPath); 
    fShaderFile.open(fragmentPath); 
    std::stringstream vShaderStream, fShaderStream; 

    vShaderStream << vShaderFile.rdbuf(); 
    fShaderStream << fShaderFile.rdbuf(); 

    vShaderFile.close(); 
    fShaderFile.close(); 

    vertexCode = vShaderStream.str(); 
    fragmentCode = fShaderStream.str(); 
} 
catch(std::ifstream::failure error) 
{ 
    std::cout << "Error: Shader file not successfully read." << std::endl; 
} 

GLuint vertex, fragment; 
GLchar infoLog[512]; 

const GLchar* vertShaderCode = vertexCode.c_str(); 
vertex = glCreateShader(GL_VERTEX_SHADER); 
glShaderSource(vertex, 1, &vertShaderCode, NULL); 
glCompileShader(vertex); 

const GLchar* fragShaderCode = fragmentCode.c_str(); 
fragment = glCreateShader(GL_FRAGMENT_SHADER); 
glShaderSource(fragment, 1, &fragShaderCode, NULL); 
glCompileShader(fragment); 

program = glCreateProgram(); 
glAttachShader(program, vertex); 
glAttachShader(program, fragment); 
glLinkProgram(program); 

glDeleteShader(vertex); 
glDeleteShader(fragment); 

GLfloat vertices[] = { 
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 
    0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 
    0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 
    -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 
    -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 
}; 

GLuint VAO, VBO; 
glGenVertexArrays(1, &VAO); 
glGenBuffers(1, &VBO); 
glBindVertexArray(VAO); 
glBindBuffer(GL_ARRAY_BUFFER, VBO); 
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 
         5 * sizeof(GLfloat), (GLvoid*)0); 
glEnableVertexAttribArray(0); 

glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), 
         (GLvoid*)(3 * sizeof(GLfloat))); 
glEnableVertexAttribArray(1); 

GLuint texture0, texture1; 

glGenTextures(1, &texture0); 
glBindTexture(GL_TEXTURE_2D, texture0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
unsigned char* image = SOIL_load_image("container.jpg", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 
GLint uniform = glGetUniformLocation(program, "texture0"); 
glUniform1i(uniform, 0); 

glGenTextures(1, &texture1); 
glBindTexture(GL_TEXTURE_2D, texture1); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
image = SOIL_load_image("awesomeface.png", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 
uniform = glGetUniformLocation(program, "texture1"); 
glUniform1i(uniform, 1); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, texture0); 
glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, texture1); 

while (!glfwWindowShouldClose(display)) 
{ 
    glClearColor(0.761f, 0.698f, 0.502f, 1.0f); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

    glUseProgram(program); 

    glBindVertexArray(VAO); 
    glDrawArrays(GL_TRIANGLES, 0, 6); 

    glfwSwapBuffers(display); 
    glfwPollEvents(); 
} 

glDeleteVertexArrays(1, &VAO); 
glDeleteBuffers(1, &VBO); 

return EXIT_SUCCESS; 
} 

关联GLSL着色器文件是如下: 顶点着色器:

#version 400 core 
layout (location = 0) in vec3 position; 
layout (location = 1) in vec2 texCoord; 

out vec2 TexCoord; 


void main() 
{ 
gl_Position = vec4(position, 1.0f); 
TexCoord = vec2(texCoord.x, 1.0 - texCoord.y); 
} 

片段着色器:

#version 400 core 
in vec2 TexCoord; 

out vec4 fragColor; 

uniform sampler2D texture0; 
uniform sampler2D texture1; 


void main() 
{ 
vec4 color1 = texture(texture0, TexCoord); 
vec4 color2 = texture(texture1, TexCoord); 
fragColor = mix(color1, color2, 0.4f); 
} 

回答

3
glUniform1i(uniform, 0); 

Thi s函数作用于当前正在使用的程序。在渲染循环之前,您不要调用glUseProgram。所以它应该给你一个GL_INVALID_OPERATION错误,因此什么都不做。

在设置统一值之前,您应该使用来自GL 4.1+(它接受其操作的程序)的glProgramUniform或调用glUseProgram

0

在代码的这一部分:

GLuint texture0, texture1; 

glGenTextures(1, &texture0); 
glBindTexture(GL_TEXTURE_2D, texture0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
unsigned char* image = SOIL_load_image("container.jpg", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 
//GLint uniform = glGetUniformLocation(program, "texture0"); 
//glUniform1i(uniform, 0); 

glGenTextures(1, &texture1); 
glBindTexture(GL_TEXTURE_2D, texture1); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
image = SOIL_load_image("awesomeface.png", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 
//uniform = glGetUniformLocation(program, "texture1"); 
//glUniform1i(uniform, 1); 

//glActiveTexture(GL_TEXTURE0); 
//glBindTexture(GL_TEXTURE_2D, texture0); 
//glActiveTexture(GL_TEXTURE1); 
//glBindTexture(GL_TEXTURE_2D, texture1); 

取下上述部分中的注释行。只需首先加载图像; 不用担心制服,并且不要在这里绑定它们。在设置任何制服之前,您需要先着色您的着色器/程序。

这部分现在看起来应该是这样:

GLuint texture0, texture1; 
// Setup Texture1 
glGenTextures(1, &texture0); 
glBindTexture(GL_TEXTURE_2D, texture0); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
unsigned char* image = SOIL_load_image("container.jpg", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 
// Setup Texture 2 
glGenTextures(1, &texture1); 
glBindTexture(GL_TEXTURE_2D, texture1); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
image = SOIL_load_image("awesomeface.png", 
    &width, &height, 0, SOIL_LOAD_RGB); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, 
    GL_RGB, GL_UNSIGNED_BYTE, image); 
glGenerateMipmap(GL_TEXTURE_2D); 
SOIL_free_image_data(image); 

现在以后你有设置你的两个纹理和您已释放土壤资源后,您将下一步需要做的是useactivate着色器-程序。然后渲染循环中

// After activating the shader set your uniforms here before your 
// render loop. You don't want to do this on every iteration. 
glUniform1i(glGetUniformLocation(program, "texture1"), 0); 
glUniform1i(glGetUniformLocation(program, "texture2"), 1); 

您处理或处理任何时间&输入信息后和你设置明确的颜色和:

glUseProgram(program);// Need to activate your shader before setting any uniforms 

那之后,你可以在你的渲染循环之前获得你的制服清除颜色缓冲区是你想要绑定纹理的地方和时间。

while (!glfwWindowShouldClose(display)) { 
    // time 
    ... 
    // input 
    ... 
    // color buffer 
    ... 
    // Bind textures 
    glActiveTexture(GL_TEXTURE0); 
    glBindTexture(GL_TEXTURE_2D, texture1); 
    glActiveTexture(GL_TEXTURE1); 
    glBindTexture(GL_TEXTURE_2D, texture2); 

    // now render the container using the shader 
    glUseProgram(program); 
    glBindVertexArray(VAO); 
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 

    // Swap buffers 

} // end loop 

另外,作为一个侧面说明,你可以在你fragement着色器做到这一点:

#version 330 core 
out vec4 FragColor; 

in vec3 ourColor; 
in vec2 TexCoord; 

// texture samplers 
uniform sampler2D texture1; 
uniform sampler2D texture2; 

void main() { 
    // linearly interpolate between both textures 
    FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.4); 
} 

这基本上是一样的,你有什么上面,但被写在一个单一的代码行它不会诉诸使用2个局部变量。记住片段着色器是昂贵的,因为它们为渲染循环的每个迭代运行每个像素或片段。在我所展示的内容中,它看起来比您的更复杂,但效率更高。祝贺www.learnopengl.com

相关问题