2017-12-18 214 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

相關問題