2017-12-18 14 views
0

ユニフォームサンプラー2Dを介してフラグメントシェーダーに2つのテクスチャーを送るのに問題があります。私のフラグメントシェーダは2つのユニフォームを持っていますが、私のコードが両方のサンプラーに同じイメージを送るようです。最初にバインドされたテクスチャは、両方のユニフォームに自動的にバインドされているようです。OpenGLの両方のユニフォームサンプラー2Dは同じ画像を持っています

完全な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現在使用されているプログラムに対して機能します。レンダーループまで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); 

今、あなたはあなたの2つのテクスチャのセットアップを持っていた後、あなたが次に何をする必要がありますどのような土壌からリソースを解放した後useまたはactivateあなたのシェーダにあります-プログラム。

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 

あなた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

関連する問題