main.cpp
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#include <fstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <SOIL/SOIL.h>
typedef struct vertex{
float x; float y; float z;
float texX; float texY;
float texIndex;
} vertex;
void readTextFile(const char* path, std::string* dst);
int main(){
std::cout << 3 << std::endl;
GLFWwindow* window;
if(!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(640, 480, "Geometry Shader Bathing with Texture Atlas", NULL, NULL);
if(!window){
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
gladLoadGL();
glfwSwapInterval(1);
glFrontFace(GL_CW);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//create and set vertex buffer
vertex vertices[] = {
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f,
-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
};
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
//create vertex shader
std::string* shaderSource = new std::string();
readTextFile("shader/vertexShader.glsl", shaderSource);
const char* vertexShaderSourcePtr = shaderSource->c_str();
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSourcePtr, NULL);
glCompileShader(vertexShader);
GLint status;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
char buffer[512];
glGetShaderInfoLog(vertexShader, 512, NULL, buffer);
std::cout << "vertexShader FAIL : " << std::endl <<
shaderSource <<std::endl
<< buffer << std::endl;
}else{
std::cout << "vertexShader compile success!" << std::endl;
}
//create fragment shader
readTextFile("shader/fragmentShader.glsl", shaderSource);
const char* fragmentShaderSourcePtr = shaderSource->c_str();
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSourcePtr, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
char buffer[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, buffer);
std::cout << "fragmentShader FAIL : " << std::endl <<
shaderSource <<std::endl
<< buffer << std::endl;
}else{
std::cout << "fragmentShader compile success!" << std::endl;
}
delete shaderSource;
//create and set program
GLint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
glBindAttribLocation(program, 0, "inPos");
glBindAttribLocation(program, 1, "inTex");
glBindAttribLocation(program, 2, "inTexIndex");
glLinkProgram(program);
//set frameBuffer(renderTarget) index and fragmentShader output name
glBindFragDataLocation(program, 0, "outColor");
glUseProgram(program);
//create and set texture
int width = 384;
int height = 384;
unsigned char* textureRawData0 = SOIL_load_image("resource/character/test0.png", &width, &height, 0, SOIL_LOAD_RGBA);
unsigned char* textureRawData1 = SOIL_load_image("resource/character/test1.png", &width, &height, 0, SOIL_LOAD_RGBA);
glUniform1i(glGetUniformLocation(program, "texture0"), 0);
glUniform1i(glGetUniformLocation(program, "texture1"), 1);
GLuint texture1;
glGenTextures(1, &texture1);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData0);
SOIL_free_image_data(textureRawData0);
std:: cout << "texture0: " << glGetUniformLocation(program, "texture0") << std::endl;
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 texture2;
glGenTextures(1, &texture2);
glActiveTexture(GL_TEXTURE0 + 1);
glBindTexture(GL_TEXTURE_2D, texture2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureRawData1);
SOIL_free_image_data(textureRawData1);
std:: cout << "texture1: " << glGetUniformLocation(program, "texture1") << std::endl;
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);
//input layout : vertex Attribute
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glLinkProgram(program);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));
while(!glfwWindowShouldClose(window)){
int width, height;
glfwGetFramebufferSize(window, &width, &height);
glViewport(0, 0, width, height);
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 12);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
void readTextFile(const char* path, std::string* dst){
std::ifstream f;
f.open(path);
if(f.is_open()){
std::string buff;
dst->clear();
while(!f.eof()){
std::getline(f, buff);
dst->append(buff);
dst->push_back('\n');
}
dst->push_back('\0');
f.close();
}else{
std::cout << "파일 열기 실패 : " << *dst << std::endl;
}
}
ps
#version 330 core
in vec2 outTex;
in float outTexIndex;
out vec4 outColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main(){
if(outTexIndex == 0.0f){
outColor = texture(texture0, outTex);
}
else if(outTexIndex == 1.0f){
outColor = texture(texture1, outTex) + vec4(0.5f, 0.5f, 0.5f, 1.0f);
}
}
The input layout(vertex attribute) works fine. TexIndex is transferred correctly. 1.0f and 0.0f
But the problem is
//fragment shader
texture(texture0, outTex);
texture(texture1, outTex);
both returns same texture color but it is actually different texture from test1.png and test2.png. what is the problem with my code?
++ I tried below fragment shader following the answer of @Rabbid76
#version 330 core
in vec2 outTex;
in float outTexIndex;
out vec4 outColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
vec4 c1 = texture(texture0, outTex) + vec4(0.5f, 0.0f, 0.0f, 1.0f);
vec4 c2 = texture(texture1, outTex) + vec4(0.0f, 0.5f, 0.0f, 1.0f);
outColor = mix(c1, c2, outTexIndex);
}
Color applied but still sampling from same the texture. looks like somehow glActiveTexture(i); doesn't work.
ps. test1.png and test2.png is completely different picture. above screenshot is test1.png
++ when I changed
glGenTexture(1, &texture0);
glGenTexture(1, &texture1);
to
glGenTexture(0, &texture0);
glGenTexture(0, &texture1);
then sampler2D texture0 and sampler2D texture1 both sample from texture1 test1.png (not form texture0 which is test0.png)
what is happening?
++
vs
#version 330
in vec3 inPos;
in vec2 inTex;
in float inTexIndex;
out vec2 outTex;
out float outTexIndex;
void main(){
outTex = inTex;
gl_position = vec4(inPos, 1.0f);
outTexIndex = inTexIndex;
}
I thought if I have a compiled example of multiple textures that working no problem, then I can find the problem of my code changing my code line to line comparing with the example. So I found this one.
It was SDL based. So I changed initialization code and loop to glfw. And It worked fine on my environment.
Even after I changed my code's texture loading part completely same with the example, the problem wasn't solved. So it must be other part that makes the problem. Finally, I found this.
//input layout : vertex Attribute
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
//*****here!*****
//glLinkProgram(program);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(vertex), 0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(vertex), (void*)(5 * sizeof(float)));
After I just add two characters "//", result was shown as I intended. I'm not sure about the reason that one line of code makes problem.