OpenGL均匀采样器2D具有相同的图像

问题描述 投票:0回答:2

我无法通过统一的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);
}
c++ opengl glfw glm-math
2个回答
3
投票
glUniform1i(uniform, 0);

此功能作用于当前正在使用的程序。在渲染循环之前,不要调用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);

现在,在设置好两个纹理之后,从SOIL中释放资源后,接下来需要做的就是useactivate你的着色器程序。

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

之后,你可以在渲染循环之前获得你的制服:

// 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 );

然后在处理或处理任何时间和输入信息之后的渲染循环中,并在设置清晰颜色并清除颜色缓冲区后,您想要绑定纹理的位置和时间。

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

另外作为旁注,您可以在片段着色器中执行此操作:

#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

© www.soinside.com 2019 - 2024. All rights reserved.