I tried to load the same model(modeled in 3Ds max) in opengl, but with different textures. The problem is, that when I try to bind the Texture with glBindTexture after I have acitvated the texture, then it disappears. Before I changed the textures in 3Ds max, it always has show me the model in black color (just in opengl). But I havenĀ“t even assign black color to my model. My image "model-image.png" also contains all textures, that I have assign to my object. So am I missing something?
Thanks for your help in advance.
void initDrawing()
{
glEnable(GL_DEPTH_TEST);
program = glCreateProgram();
std::string shaderV = Utilities::loadFile("shader.vert");
std::string shaderF = Utilities::loadFile("shader.frag");
program = Utilities::compileShader(shaderV, shaderF);
Utilities::loadObj("model.obj", obj);
Utilities::loadPNG("model-image.png", diffuse);
glEnable(GL_TEXTURE_2D);
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glGenBuffers(1, &vPosition);
glBindBuffer(GL_ARRAY_BUFFER, vPosition);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*obj.vertices.size(), &obj.vertices[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vPosition);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
GLuint vCoordinates;
glGenBuffers(1, &vCoordinates);
glBindBuffer(GL_ARRAY_BUFFER, vCoordinates);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2)*obj.textureCoordinates.size(), &obj.textureCoordinates[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, vCoordinates);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
glGenTextures(2, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, diffuse.width, diffuse.height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
&diffuse.colors[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glUseProgram(program);
ModelView = glGetUniformLocation(program, "ModelView");
Projection = glGetUniformLocation(program, "Projection");
Diffuse = glGetUniformLocation(program, "Diffuse");
}
void display()
{
// background color
const GLfloat color[] = { 0.5, 0.5, 0.5, 1 };
glClear(GL_DEPTH_BUFFER_BIT);
glClearBufferfv(GL_COLOR, 0, color);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
modelView = view * model;
glUniformMatrix4fv(ModelView, 1, GL_FALSE, glm::value_ptr(modelView));
glUniformMatrix4fv(Projection, 1, GL_FALSE, glm::value_ptr(projection));
glUniform1i(Diffuse, 0);
glDrawArrays(GL_TRIANGLES, 0, obj.vertices.size());
glutSwapBuffers();
}
My Shader:
fragment shader:
uniform sampler2D Diffuse;
in vec2 fUV;
out vec3 color;
//main for the color
void main(void)
{
color = texture(Diffuse, fUV).rgb;
}
vertex Shader:
layout (location = 0) in vec4 vPosition;
layout (location = 2) in vec2 vCoordinates;
uniform mat4 ModelView;
uniform mat4 Projection;
out vec2 fUV;
void main(void)
{
gl_Position = Projection * ModelView * vPosition;
fUV = vCoordinates;
}
My guess is that when you say
layout(location = 2) in vec2 vCoordinates;
you really mean to say
layout(location = 1) in vec2 vCoordinates;
considering you never enable vertex attribute 2.
Related
I exported the Blender Box as a Collada file, I am loading it with Assimp, yet it does not draw properly.
Here is how it looks:
I have tried using .fbx and .obj without success.
is this an error in my code, or is the vertex data not correct?
I checked the normals, they all point in the proper direction,
whats leads me to believe that the orientation of the faces is correct.
Here is my Code:
#include<assimp/Importer.hpp>
#include<assimp/postprocess.h>
#include<assimp/scene.h>
#include<vector>
#include<iostream>
#include<GL/glew.h>
#include<glm/glm.hpp>
#include<glm/gtx/quaternion.hpp>
#include<glm/gtc/quaternion.hpp>
#include<glm/gtc/matrix_transform.hpp>
#include<SFML/Window.hpp>
#include<SFML/OpenGL.hpp>
#include<SFML/Graphics.hpp>
#include"Shader.h"
#include"vertex.h"
#include"Cam.h"
#include"obj.h"
int main() {
glewExperimental = GL_TRUE;
if (!glewInit()) {
std::cout << "Glew Failed to initialize" << std::endl;
return -5;
}
glEnable(GL_DEPTH_TEST);
////////////////////////////// WINDOW SHADER CAMERA ///////////////////////////
sf::Window window(sf::VideoMode(800, 600), "OpenGL");
window.setActive(true);
Shader Shader1("vss_min.glsl", "fss_min.glsl");
Cam camera(window);
glm::mat4 modelMatrix(1.0);
modelMatrix = glm::scale(modelMatrix, glm::vec3(0.2, 0.2f, 0.2f));
///////////////////////////// MESH /////////////////////////////////////////
std::vector<vertex> vertices;
std::vector<std::uint32_t> indices;
Assimp::Importer importer;
const aiScene* s = importer.ReadFile("c:/meshes/ext/buntekiste.fbx",aiProcess_Debone);
aiMesh* mesh = s->mMeshes[0];
for (std::uint32_t it = 0; it < mesh->mNumVertices;it++) {
vertex v;
if (mesh->HasPositions())v.pos = vec3(mesh->mVertices[it]);
if (mesh->HasNormals())v.normal = vec3(mesh->mNormals[it]);
if (mesh->HasVertexColors(0))v.color = vec4(mesh->mColors[0][it]);
if (mesh->HasTextureCoords(0))v.uv = vec2(mesh->mTextureCoords[0][it]);
vertices.push_back(v);
}
for (std::uint32_t it = 0; it < mesh->mNumFaces; it++) {
indices.push_back(mesh->mFaces[it].mIndices[0]);
indices.push_back(mesh->mFaces[it].mIndices[1]);
indices.push_back(mesh->mFaces[it].mIndices[2]);
}
std::uint32_t VAO, VBO, IBO, TID;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER,VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(vertex), vertices.data(), GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (void*)(3*sizeof(float)));
glEnableVertexAttribArray(1);
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (void*)(6*sizeof(float)));
glEnableVertexAttribArray(2);
glVertexAttribPointer(3, 2, GL_FLOAT, GL_FALSE, 12 * sizeof(float), (void*)(10*sizeof(float)));
glEnableVertexAttribArray(3);
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(std::uint32_t), indices.data(), GL_STATIC_DRAW);
/////////////////////////////// TEXTURE //////////////////////////////////////////////////////
sf::Image img;
img.loadFromFile("c:/textures/buntekiste.png");
glGenTextures(1, &TID);
glBindTexture(GL_TEXTURE_2D, TID);
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_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (img.getPixelsPtr()) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, img.getSize().x, img.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.getPixelsPtr());
glGenerateMipmap(GL_TEXTURE_2D);
}
else {
std::cout << "Failed to load texture" << std::endl;
return -3;
}
////////////////////////////// MAINLOOP ///////////////////////////////////////////////////////
bool running = true;
while (running)
{
// handle events
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
// end the program
running = false;
}
else if (event.type == sf::Event::Resized)
{
// adjust the viewport when the window is resized
glViewport(0, 0, event.size.width, event.size.height);
}
}
///////////////////// DRAWSTUFF /////////////////////////////////////////
camera.update(),
glClearColor(0.3f, 0.0f, 0.8f,0.7f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 mvp = modelMatrix;
Shader1.set4x4("Model", modelMatrix);
Shader1.set4x4("View", camera.getView());
Shader1.set4x4("Projection", camera.getProjection());
glBindVertexArray(VAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, TID);
Shader1.use();
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
window.display();
}
return 0;
}
FragmentShader:
#version 440
out vec4 FragColor;
in vec4 vertexColor;
in vec3 FragPos;
in vec3 normal;
in vec2 uv;
uniform int textureSwitch;
uniform vec3 lightPos;
uniform sampler2D myTexture;
void main(){
FragColor = texture(myTexture,uv);
}
VertexShader:
#version 440
layout(location =0) in vec3 Pos;
layout(location =1) in vec3 Normal;
layout(location =2) in vec4 Color;
layout(location =3) in vec2 TexCoord;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
out vec4 vertexColor;
out vec3 normal;
out vec3 FragPos;
out vec2 uv;
void main(){
mat4 mvp = Projection *View*Model;
gl_Position = mvp * vec4(Pos,1.0f);
normal = Normal;
uv = TexCoord;
vertexColor = Color;
}
I had the same problem and this works for me: add glEnable(GL_DEPTH_TEST);//enable depth buffer glCullFace(GL_FRONT);//for keep front faces and glDisable(GL_CULL_FACE); - if you have enabled GL_CULL_FACE
I did call glEnable(GL_DEPTH_TEST)
before creating the OpenGL Context.
Calling it afterwards solves it.
Ahh finally:
I have been writing a program to visualize a fractal point cloud and so far everything has been working, camera movement is using arc-ball movement centered on the origin and points are being rendered. However, I am needing to output the scene into an integrated window inside a UI so i have been trying to get frame buffers to work.
So far i have got a texture to be successfully rendered onto a quad that i am then outputting to the screen which for testing purposes is basically the same as when i was not using a fbo. My issue comes when trying to get camera movement to also display using the rendered texture. i know this is definitely possible as there are lots of examples of this but i haven't been able to get any to work with my code. I'm fairly certain my issue is with my shaders but i have scoured lots of websites, YouTube tutorials, openGL examples and found nothing that works. to the best of my knowledge i have to render the scene as normal so i have been using the same shaders that have worked for me previously for the initial rendering step but i have using my fbo instead of the default fbo
for simplicity's sake, i have just been rendering a point cube as it is faster than generating a fractal each time.
here is the main setup of the fbo, texture and rbo:
GLuint fbo;
GLuint texturebuffer;
GLuint rbo;
void initFBO(){
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glGenTextures(1, &texturebuffer);
glBindTexture(GL_TEXTURE_2D, texturebuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texturebuffer, 0);
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WINDOW_WIDTH, WINDOW_HEIGHT);
glBindRenderbuffer(GL_RENDERBUFFER, 0); // once rbo memory allocated unbind
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
}
here is the main and the draw loop:
int main(){
if(!setup())
return -1;
// // white background
glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
// GLuint programID = LoadShaders( "new_vertex_shader", "new_fragment_shader" ); // custom shader
GLuint programID = LoadShaders("new_vertex_shader", "new_fragment_shader");
GLuint modelMatrixID = glGetUniformLocation(programID, "model");
GLuint viewMatrixID = glGetUniformLocation(programID, "view");
GLuint matrixID = glGetUniformLocation(programID, "MVP");
GLuint quad_programID = LoadShaders( "screen_vertex_shader", "screen_fragment_shader" );
GLuint textureID = glGetUniformLocation(quad_programID, "screenTexture");
// initialise mvp matrices
glm::mat4 ProjectionMatrix = perspective(radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 ViewMatrix = translate(mat4(1.0f), vec3(0,0,-RADIUS));
glm::mat4 ModelMatrix = mat4(1.0f);
glm::mat4 MVP;
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
GLfloat cube[24] = {
0.5,0.5,0.5,
0.5,-0.5,0.5,
-0.5,0.5,0.5,
-0.5,-0.5,0.5,
0.5,0.5,-0.5,
0.5,-0.5,-0.5,
-0.5,-0.5,-0.5,
-0.5,0.5,-0.5
};
glBufferData(GL_ARRAY_BUFFER, sizeof(cube),cube, GL_STATIC_DRAW);
glfwSetMouseButtonCallback(window, mouseCallback);
// ################# main draw loop #######################
while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 ){
// render to fbo first
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
computeMatricesFromInputs();
ProjectionMatrix = getProjectionMatrix();
ViewMatrix = getViewMatrix();
ModelMatrix = getModelMatrix();
MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// Use our shader
glUseProgram(programID);
// Send our transformation to the currently bound shader in the "MVP" uniform
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
glUniformMatrix4fv(viewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
// render scene as normal
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // index buffer
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glPointSize(POINT_SIZE);
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDisableVertexAttribArray(0);
// bind back to default frame buffer to show on screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(quad_programID);
glEnableVertexAttribArray(0);
glBindVertexArray(quad_vertex_buffer);
glVertexAttribPointer(
0, // attribute 0. No particular reason for 0, but must match the layout in the shader.
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDisableVertexAttribArray(0);
// Swap buffers
glfwSwapBuffers(window);
glfwPollEvents();
}
vertex shader:
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 view;
uniform mat4 model;
void main(){
// Output position of the vertex, in clip space : MVP * position
gl_Position = MVP * vec4(vertexPosition_modelspace,1.0);
}
fragment shader:
#version 330 core
// Output data
out vec3 color;
void main(){
// Output color = black
color = vec3(0,0,0);
}
screen quad vertex shader:
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
TexCoords = aTexCoords;
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}
screen quad fragment shader:
#version 330 core
out vec4 FragColour;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
FragColour = texture(screenTexture, TexCoords);
}
sorry if this is quite a big block of code, im not entirely sure where the error would lie and im somewhat new to using openGL. many thanks in advance for anyhelp.
glEnableVertexAttribArray changes a state in the Vertex Array Object. It has to be done after binding the VAO by glBindVertexArray.
I assume that quad_vertex_buffer is a Vertex Array Object, even though the name "vertex_buffer" is misleading.
glBindVertexArray(quad_vertex_buffer);
glEnableVertexAttribArray(0);
When you draw the screen space quad (2nd pass), then you have to use a primitive type which generates a (filled) polygon (probably GL_TRIANGLES or GL_TRIANGLE_STRIP), rather than the point primitive type GL_POINTS:
glDrawArrays(GL_POINTS, 0, sizeof(cube));
glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(cube))
I'm working on some examples, and I was trying to pass a texture to a shader.
To build a VAO, I have this piece of code:
void PlaneShaderProgram::BuildVAO()
{
// Generate and bind the vertex array object
glGenVertexArrays(1, &_vao);
glBindVertexArray(_vao);
// Generate and bind the vertex buffer object
glGenBuffers(1, &_vbo);
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _coordinates, GL_STATIC_DRAW);
// Generate and bind the index buffer object
glGenBuffers(1, &_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), _indexes, GL_STATIC_DRAW);
// Generate and bind texture
_texture = LoadTexture("floor.bmp");
LoadAttributeVariables();
glBindVertexArray(0);
}
This is how I load the shader attributes:
void PlaneShaderProgram::LoadAttributeVariables()
{
GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
glEnableVertexAttribArray(VertexPosition_location);
glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
}
void PlaneShaderProgram::LoadUniformVariables()
{
// OpenGL Matrices
GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvpMatrix");
glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelViewProjection));
// Floor texture
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, _texture);
// GLint Texture_location = glGetUniformLocation(GetProgramID(), "texture");
// glUniform1i(Texture_location, 0);
}
And my LoatTexture:
GLuint ProgramManager::LoadTexture(const char* imagepath)
{
unsigned char * data = LoadBMP(imagepath, &width, &height);
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
return textureID;
}
Finally, my draw function, which is called in the OpenGL main loop, is the following:
void PlaneShaderProgram::DrawPlane(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
_ModelViewProjection = Projection * ModelView;
_ModelView = ModelView;
Bind();
glBindVertexArray(_vao);
LoadUniformVariables();
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
UnBind();
}
What I didn't get is that even if I didn't set the uniform texture (commented in the code) used by my shader, the plane is still draw using the texture. This makes no sense for me. Once the shader requires a sample2D, I think this shouldn't work and return some error.
Vertex Shader:
uniform mat4 mvpMatrix;
in vec4 vPosition;
smooth out vec2 uvCoord;
void main()
{
uvCoord = vPosition.xz;
gl_Position = mvpMatrix * vPosition;
}
Frag Shader:
uniform sampler2D texture;
in vec2 uvCoord;
out vec4 fragColor;
void main()
{
fragColor.rgb = texture(texture, uvCoord).rgb;
};
Am I missing something? Somehow this works I don't understand why, but I really like to.
The sampler data types in GLSL reference the texture unit, not a texture object. By default, uniforms will be initialized to 0, so if you don't set the sampler uniforms, they will sample from texture unit 0 (which is also the default unit). In your ProgramManager::LoadTexture() method, you bind the newly created texture, and very likely you are still using GL_TEXTURE0 as the currently active texture unit. You never seem to unbind it, so it is still bound at the time of the draw call, and the shader can access it.
I have the following setup for basic texture mapping
void init(void) {
glGenVertexArrays(NumVAOs, VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[6][2] = {
{ -0.90, -0.90 }, // Triangle 1
{ 0.85, -0.90 },
{ -0.90, 0.85 },
{ 0.1, 0.1 }, // UVs
{ 0.9, 0.1 },
{ 0.1, 0.9 }
};
glGenBuffers(NumBuffers, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
GLuint program = LoadShaders( "triangles.vert", "triangles.frag" );
glUseProgram(program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(vPosition);
glVertexAttribPointer(1, 2, GL_FLOAT,
GL_FALSE, 0, BUFFER_OFFSET(2*3*sizeof(GLfloat)));
glEnableVertexAttribArray(1);
GLuint sloc = glGetUniformLocation(program, "mySampler");
glUniform1i(sloc, 0);
int x,y,n;
unsigned char *data = stbi_load("bricks.jpg", &x, &y, &n, 4);
glGenTextures(1, &m_textureId);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glTexParameterf(m_textureId, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(m_textureId, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
stbi_image_free(data);
}
void display(void) {
glClear(GL_COLOR_BUFFER_BIT);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_textureId);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
glFlush();
}
Vertex Shader:
#version 330 core
layout(location = 0) in vec4 vPosition;
layout(location = 1) in vec2 uv;
out vec2 texCoord;
void
main() {
gl_Position = vPosition;
texCoord = uv;
}
Fragment Shader:
#version 330 core
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D mySampler;
void
main() {
fColor = texture(mySampler, texCoord);
}
However, nothing is displayed on the screen. If I swap out my frag shader with one that just sets a static color, I see the triangle. I have confirmed that I am getting data from the image and printed out a sample set of RGBA data that looks correct (rgb vary, but alpha is constant 0xFF). I've read at least 5 tutorials but can't seem to get it right.
I've also confirmed that if I do:
fColor = vec4(texCoord.x, texCoord.y, 0.0, 1.0);
I get a gradient of colors which I believe tells me I'm getting correctly interpolated values of my UVs coming through.
Apparently these texparams are required for some implementations
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameter( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
I'm trying out my hand at graphics, following a tutorial at http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_06
Problem: When I try to texture my cube, my sample is black.
Screenshot: http://puu.sh/2JP1H.jpg (note: I set blue = uv.x to test my UVs)
I looked at the threads OpenGL textures appear just black, and
Texture is all black, but it seemed they had different problems.
First I load my texture using SOIL image loading library:
int w, h;
unsigned char* img = SOIL_load_image("resources/images/4x4window.jpg",&w,&h,0,0);
ErrorIf(!img, "%s", SOIL_last_result());
glGenTextures(1, &texture_id);
glBindTexture(GL_TEXTURE, texture_id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,w,h,0,GL_RGB,GL_UNSIGNED_BYTE,img);
My render function where I pass my texture to the shader program:
void onDisplay()
{
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture_id);
glUniform1i(uniform_myTexture, /*GL_TEXTURE*/0);
glEnableVertexAttribArray(attribute_coord3d); // open shader var
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_verts); // put stuff in buffer
glVertexAttribPointer(attribute_coord3d, 3, GL_FLOAT, GL_FALSE, 0, 0); //send
glEnableVertexAttribArray(attribute_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords);
glVertexAttribPointer(attribute_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements);
int size;
glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size);
glDrawElements(GL_TRIANGLES, size / sizeof(GLushort), GL_UNSIGNED_SHORT, 0);
glDisableVertexAttribArray(attribute_coord3d);
glDisableVertexAttribArray(attribute_texcoord);
glutSwapBuffers();
}
Vertex Shader:
attribute vec3 coord3d;
attribute vec2 texcoord;
varying vec2 f_texcoord;
uniform mat4 mvp;
void main(void)
{
gl_Position = mvp * vec4(coord3d, 1.0);
f_texcoord = texcoord;
}
Fragment Shader:
varying vec2 f_texcoord;
uniform sampler2D mytexture;
void main(void)
{
vec4 result = texture2D(mytexture, f_texcoord);
result.z = f_texcoord.x;
result.w = 1;
gl_FragColor = result;
}
The line where the the texture is bound is:
glBindTexture(GL_TEXTURE, texture_id);
that should be:
glBindTexture(GL_TEXTURE_2D, texture_id);