I'm completely new to OpenGL and am having trouble on binding texture and shaders to VBOs works.
Here's my code.
static const char *vertexShaderSource =
"attribute highp vec3 posAttr;\n"
"attribute highp vec2 texAttr;\n"
"varying highp vec2 texCoord;\n"
"uniform highp mat4 matrix;\n"
"void main() {\n"
" texCoord = texAttr;\n"
" gl_Position = matrix * vec4(posAttr, 1.0);\n"
"}\n";
static const char *fragmentShaderSource =
"varying highp vec2 texCoord;\n"
"uniform sampler2D gSampler;\n"
"void main() {\n"
//" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" //it work
" gl_FragColor = texture2D(gSampler, texCoord);\n" //it not work
"}\n";
create buffers.
void TriangleWindow::createVertexBuffer()
{
GLfloat vertices[] = {
1.0f,1.0f,0.0f, 0.0f,0.0f,
0.0f,1.0f,1.0f, 0.5f,0.0f,
1.0f,0.0f,1.0f, 1.0f,0.0f,
0.5f,0.0f,0.0f, 0.5f,1.0f
};
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
qDebug()<<"sizeof(vertices) is "<<sizeof(vertices);
}
void TriangleWindow::createIndexBuffer()
{
GLuint indexs[] = {
0,1,3,
0,2,1,
0,3,2,
1,3,2
};
glGenBuffers(1, &m_ibo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indexs), indexs, GL_STATIC_DRAW);
qDebug()<<"sizeof(indexs) is "<<sizeof(indexs);
}
void TriangleWindow::createTextureBuffer()
{
QString resPath = "/Users/luxiaodong/Project/Demo/OpenGLES/res";
QString imgPath = QString("%1/test.png").arg(resPath);
qDebug()<<imgPath;
QImage image = QImage(imgPath).convertToFormat( QImage::Format_RGBA8888 );
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glGenTextures(1, &m_tex);
glBindTexture(GL_TEXTURE_2D, m_tex);
glTexParameterf(m_tex, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(m_tex, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(m_tex, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)image.bits() );
//glTexImage2D(GL_TEXTURE_2D, 0, 4, image.width(), image.height(), 0, GL_BGRA, GL_UNSIGNED_BYTE, image.bits());
}
initialize
void TriangleWindow::initialize()
{
createVertexBuffer();
createIndexBuffer();
createTextureBuffer();
m_program = new QOpenGLShaderProgram(this);
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertexShaderSource);
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragmentShaderSource);
m_program->link();
m_posAttr = m_program->attributeLocation("posAttr");
m_texAttr = m_program->attributeLocation("texAttr");
m_matrixUniform = m_program->uniformLocation("matrix");
m_gSampler = m_program->uniformLocation("gSampler");
m_program->setUniformValue(m_gSampler, 0);
qDebug()<<m_posAttr<<m_texAttr<<m_matrixUniform<<m_gSampler;
}
render
void TriangleWindow::render()
{
const qreal retinaScale = devicePixelRatio();
glViewport(0, 0, width() * retinaScale, height() * retinaScale);
glClear(GL_COLOR_BUFFER_BIT);
m_program->bind();
QMatrix4x4 matrix;
matrix.perspective(60.0f, 4.0f/3.0f, 0.1f, 100.0f);
matrix.translate(0, 0, -4);
matrix.rotate(100.0f * m_frame/screen()->refreshRate(), 0, 1, 0);
m_program->setUniformValue(m_matrixUniform, matrix);
m_program->setUniformValue(m_gSampler, 0);
glEnableVertexAttribArray(m_posAttr);
glEnableVertexAttribArray(m_texAttr);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glVertexAttribPointer(m_posAttr, 3, GL_FLOAT, GL_FALSE, 20, (const GLvoid*)0);
glVertexAttribPointer(m_texAttr, 2, GL_FLOAT, GL_FALSE, 20, (const GLvoid*)12);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, m_tex);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, (const GLvoid*)0 );
glDisableVertexAttribArray(m_texAttr);
glDisableVertexAttribArray(m_posAttr);
m_program->release();
++m_frame;
}
I'm not sure what i am doing wrong. I tried different things with the shader but it seems it doesn't matter. in fragmentShader.
" gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" //it work
" gl_FragColor = texture2D(gSampler, texCoord);\n" //it not work
Is this a problem with the shader I'm using, or is it something else that I'm not understanding?
Either the uniform(gSampler) or attribute(texAttr) should be the reason. To verify texAttr, use this as
gl_FragColor = vec4(texCoord.x,texCoord.y,0.0,1.0);
if your output is in some color then there is no problem in texAttr. I don't see any coding issue for texAttr. Anyway check once.
To verify gSampler, verify the glUniform1i(m_gSampler,unit), the unit should match the value(GL_TEXTURE0) you used to bind before glDrawElement.
Related
When I use glm::scale to update the model matrix in my vertex shader, no matter what I do, it will always scale it down. Anyone know what I'm doing wrong? The image will sometimes flip up and down too.
The key == 'w' and key == 's' do the exact same thing despite the code being different, the goal is to make the model grow bigger by pressing W and smaller by pressing S. But right now it just gets smaller with both presses.
The relevant code used to scale according to key press is:
if (key == 'w') {
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 's') {
model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
The whole code is:
#include <Windows.h>
#include <GL\glew.h>
#include <GL\freeglut.h>
#include <iostream>
#include <SOIL.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "OBJ.h"
const char* vs = "#version 330 core\n"
"layout (location = 0) in vec3 pos;\n"
"layout (location = 1) in vec2 texpos;\n"
"out vec2 texCoords;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(pos, 1);\n"
"texCoords = texpos;\n"
"}\0";
const char* fs = "#version 330 core\n"
"in vec2 texCoords;\n"
"out vec4 fragColor;\n"
"uniform sampler2D tex;\n"
"void main()\n"
"{\n"
"fragColor = texture(tex, texCoords);"
"}\0";
float verts[] = {
0, 1, 0, 0.5, 1,
-1, -1, 0, 0, 0,
1, -1, 0, 1, 0
};
unsigned short indices[] = {
0, 1, 2
};
unsigned int vao, vbo, ebo, prog, vert, frag, texid;
glm::mat4 model, view, projection;
void changeViewPort(int w, int h)
{
glViewport(0, 0, w, h);
}
void render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindVertexArray(vao);
glBindTexture(GL_TEXTURE_2D, texid);
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, 0);
glutSwapBuffers();
}
void initGL() {
//Context stuff
glViewport(0, 0, 800, 600);
glClearColor(0.5, 0.5, 0.5, 1);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//Shader stuff
int success;
prog = glCreateProgram();
vert = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vert, 1, &vs, NULL);
glCompileShader(vert);
glGetShaderiv(vert, GL_COMPILE_STATUS, &success);
std::cout << "Vertex shader " << (success ? "compiled" : "not compiled") << std::endl;
frag = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(frag, 1, &fs, NULL);
glCompileShader(frag);
glGetShaderiv(frag, GL_COMPILE_STATUS, &success);
std::cout << "Fragment shader " << (success ? "compiled" : "not compiled") << std::endl;
glAttachShader(prog, vert);
glAttachShader(prog, frag);
glLinkProgram(prog);
glUseProgram(prog);
glGetShaderiv(prog, GL_LINK_STATUS, &success);
std::cout << "Program " << (success ? "linked" : "not linked") << std::endl;
glDeleteShader(vert);
glDeleteShader(frag);
//Vertex stuff
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), &verts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), 0);
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GL_FLOAT), (void*)(3 * sizeof(GL_FLOAT)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
//Texture stuff
int width, height;
unsigned char* texData = SOIL_load_image("brick.png", &width, &height, NULL, SOIL_LOAD_RGBA);
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
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_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (texData) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texData);
glGenerateMipmap(GL_TEXTURE_2D);
} else {
std::cout << "Texture not loaded." << std::endl;
}
glBindTexture(GL_TEXTURE_2D, 0);
SOIL_free_image_data(texData);
//Matrix stuff
//Model matrix
model = glm::mat4(1.0f);
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int modelMatrix = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(modelMatrix, 1, GL_FALSE, glm::value_ptr(model));
//View matrix
view = glm::mat4(1.0f);
view = glm::translate(view, glm::vec3(0, 0, -3));
int viewMatrix = glGetUniformLocation(prog, "view");
glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(view));
//Projection matrix, something is messing up here
projection = glm::mat4(1.0f);
projection = glm::perspective(glm::radians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f);
int projectionMatrix = glGetUniformLocation(prog, "projection");
glUniformMatrix4fv(projectionMatrix, 1, GL_FALSE, glm::value_ptr(projection));
}
void input(unsigned char key, int x, int y) {
if (key == 'a') {
model = glm::translate(model, glm::vec3(-0.5, 0, 0));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'd') {
model = glm::translate(model, glm::vec3(0.5, 0, 0));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'w') {
model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 's') {
model = glm::scale(model, glm::vec3(-0.5, -0.5, -0.5));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'q') {
model = glm::rotate(model, glm::radians(45.0f), glm::vec3(0, 0, 1));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
if (key == 'e') {
model = glm::rotate(model, glm::radians(-45.0f), glm::vec3(0, 0, 1));
int loc = glGetUniformLocation(prog, "model");
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(model));
}
glutPostRedisplay();
}
int main(int argc, char* argv[]) {
// Initialize GLUT
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OBJ Viewer");
glutReshapeFunc(changeViewPort);
glutDisplayFunc(render);
glutKeyboardFunc(input);
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "GLEW error");
return 1;
}
initGL();
glutMainLoop();
return 0;
}
It's not clear what you mean by half a coordinate, but it's clear that you want to change size by an absolute value, while the scale matrix is relative to the model. In fact, you should also consider what happens when the model is not around the origin - the space between the model and the origin is also scaled!
to get an absolute size change, I'd suggest to calculate the model's bounding box, and the desired size. The ratio of the two will go into the scale function. For example, if the model's bounding box is (20, 10, 5), and you want it to be (19.5, 9.5, 4.5), then you need scale(20/19.5, 10/19.5, 5/4.5).
Calculating a model's bounding box should be done after each rotation change. In the general case, you can do it on the CPU, going over the CPU-transformed vertices and taking the min and max of each coordinate. There may be faster methods depending on your special circumstances.
When you scale your model, you pass the model matrix and scale vector to glm::scale function. When you do model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5));, this means multiplying your model size by 0.5, instead of adding. Same with -0.5. That's why your model always scales down.
As far as I understand, you want your model to scale up and down by 50 % when pressing 'w' and 's' respectively. So, simply use model = glm::scale(model, glm::vec3(1.5, 1.5, 1.5)); to scale up and model = glm::scale(model, glm::vec3(0.5, 0.5, 0.5)); to scale down.
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.
I'm trying to enable mutlisampling and alpha-to-coverage for an FBO. Using the default framebuffer, all I have to do is call glEnable(GL_MULTISAMPLE) and glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE). However, I am unable to achieve the same effect using my own FBO.
My goal: Draw the scene to an FBO the same way it would be drawn to the default framebuffer with the above properties. From there I want to be able to use the image as a texture for future passes through a shader.
This works: Code for making an FBO without multisampling/alpha-to-coverage, 1 color attachment, 1 depth attachment:
// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,defaultColorAttachment0);
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_RGBA,screenWidth,screenHeight,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL);
// Bind the texture to the FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, defaultColorAttachment0,0);
// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer);
This doesn't work. Code trying to make a multisampled FBO:
// Generate the color attachment
glGenTextures(1,&defaultColorAttachment0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, defaultColorAttachment0);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA, screenWidth, screenHeight, GL_FALSE);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, defaultColorAttachment0,0);
// Generate the depth attachment
glGenRenderbuffers(1,&defaultDepthBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, defaultDepthBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, screenWidth, screenHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, defaultDepthBuffer);
I have tried looking through the OpenGL wiki on this, although the it's incomplete (various unfinished headings make it look unprofessional). glGetError never complains. I've tried messing around with this, but I either get a black screen or a screen full of garbage pixels.
Main Question: What things do I need to consider/change and where (FBO creation, textures, shaders) in order to get multisampling and alpha-to-coverage to work with an FBO?
You need to allocate a multisampled depth buffer for this to work correctly and give it the same number of samples as your color buffer. In other words, you should be calling glRenderbufferStorageMultisample (...) instead of glRenderbufferStorage (...).
Your FBO should be failing a completeness check the way it is allocated right now. A call to glCheckFramebufferStatus (...) ought to return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE because your depth buffer has exactly 1 sample and your color buffer attachment has 4.
Since you are also using a multisampled texture attachment in this FBO, you should be aware of differences between sampling a single-sampled texture vs. multisampled in GLSL shaders.
Multisampled textures have a special sampler uniform type (e.g. sampler2DMS) and you have to explicitly fetch each sample in the texture by its integer (non-normalized) texel coordinate and sample index using texelFetch (...). This also means that they cannot be filtered or mip-mapped.
You probably do not want a multisampled texture in this case, you probably want to use glBlitFramebuffer (...) to do the MSAA resolve into a single-sampled FBO. If you do this instead you can read the anti-aliased results in your shaders rather than having to fetch each sample and implement the anti-aliasing yourself.
Here is a working example to go along with the accepted answer. It is a modified example of the triangle example from the LearnopenGL tutorials to draw a MSAA custom framebuffer to a quad which is then draw to the default framebuffer (the screen):
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
const char *postProcessvertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec2 position;\n"
"layout (location = 1) in vec2 inTexCoord;\n"
"out vec2 texCoord;\n"
"void main(){\n"
" texCoord = inTexCoord;\n"
" gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);\n"
"}\n\0";
const char *postProcessFragmentShaderSource = "#version 330 core\n"
"out vec4 fragmentColor;\n"
"in vec2 texCoord;\n"
"//notice the sampler\n"
"uniform sampler2DMS screencapture;\n"
"uniform int viewport_width;\n"
"uniform int viewport_height;\n"
"void main(){\n"
" //texelFetch requires a vec of ints for indexing (since we're indexing pixel locations)\n"
" //texture coords is range [0, 1], we need range [0, viewport_dim].\n"
" //texture coords are essentially a percentage, so we can multiply text coords by total size \n"
" ivec2 vpCoords = ivec2(viewport_width, viewport_height);\n"
" vpCoords.x = int(vpCoords.x * texCoord.x); \n"
" vpCoords.y = int(vpCoords.y * texCoord.y);\n"
" //do a simple average since this is just a demo\n"
" vec4 sample1 = texelFetch(screencapture, vpCoords, 0);\n"
" vec4 sample2 = texelFetch(screencapture, vpCoords, 1);\n"
" vec4 sample3 = texelFetch(screencapture, vpCoords, 2);\n"
" vec4 sample4 = texelFetch(screencapture, vpCoords, 3);\n"
" fragmentColor = vec4(sample1 + sample2 + sample3 + sample4) / 4.0f;\n"
"}\n\0";
int main()
{
int width = 800;
int height = 600;
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
GLFWwindow* window = glfwCreateWindow(width, height, "OpenglContext", nullptr, nullptr);
if (!window)
{
std::cerr << "failed to create window" << std::endl;
exit(-1);
}
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cerr << "failed to initialize glad with processes " << std::endl;
exit(-1);
}
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
int samples = 4;
float quadVerts[] = {
-1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 0.0, 1.0,
1.0, -1.0, 1.0, 0.0,
1.0, -1.0, 1.0, 0.0,
-1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 1.0
};
GLuint postVAO;
glGenVertexArrays(1, &postVAO);
glBindVertexArray(postVAO);
GLuint postVBO;
glGenBuffers(1, &postVBO);
glBindBuffer(GL_ARRAY_BUFFER, postVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVerts), quadVerts, GL_STATIC_DRAW);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), reinterpret_cast<void*>(0));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), reinterpret_cast<void*>(2 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindVertexArray(0);
GLuint msaaFB;
glGenFramebuffers(1, &msaaFB);
glBindFramebuffer(GL_FRAMEBUFFER, msaaFB); //bind both read/write to the target framebuffer
GLuint texMutiSampleColor;
glGenTextures(1, &texMutiSampleColor);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, width, height, GL_TRUE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// vertex shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
// fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
// link shaders
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
//postprocess vertex shader
unsigned int postProcessVertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(postProcessVertexShader, 1, &postProcessvertexShaderSource, NULL);
glCompileShader(postProcessVertexShader);
// postprocess fragment shader
unsigned int postProcessFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(postProcessFragmentShader, 1, &postProcessFragmentShaderSource, NULL);
glCompileShader(postProcessFragmentShader);
// check for shader compile errors
// link shaders
unsigned int postProcessShaderProgram = glCreateProgram();
glAttachShader(postProcessShaderProgram, postProcessVertexShader);
glAttachShader(postProcessShaderProgram, postProcessFragmentShader);
glLinkProgram(postProcessShaderProgram);
// check for linking errors
glDeleteShader(postProcessVertexShader);
glDeleteShader(postProcessFragmentShader);
glUseProgram(postProcessShaderProgram);
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "screencapture"), 0);
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "viewport_width"), width);
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "viewport_height"), height);
float vertices[] = {
-0.5f, -0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
0.0f, 0.5f, 0.0f
};
unsigned int VBO, VAO;
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, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
bool use_msaa = true;
while (!glfwWindowShouldClose(window))
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS)
use_msaa = true;
if (glfwGetKey(window, GLFW_KEY_T) == GLFW_PRESS)
use_msaa = false;
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (use_msaa) {
glBindFramebuffer(GL_FRAMEBUFFER, msaaFB);
}
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
if (use_msaa) {
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glUseProgram(postProcessShaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor);
glBindVertexArray(postVAO);
glDrawArrays(GL_TRIANGLES, 0, 6);
}
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
// cleanup
}
Demo:
Thankyou Matt Stone from the comment section of LearnOpenGL for the working code.
Adding to jackw11111's answer, I wanted to test this sample code in python. Enclosed is my near 1:1 translation to python of code apparently by Matt Stone in comments of LearnOpenGL. Tested on Ubuntu and MacOS.
## Not needed for python.
## #include <glad/glad.h>
# Setup might be something like:
# python3 -m venv venv_msaa
# source venv_msaa/bin/activate
# pip install PyOpenGL glfw numpy
# Note: On a MacOS hidpi screen, the results will vary.
import ctypes
import numpy as np
import glfw
from OpenGL.GL import *
VERTEX_SHADER_SOURCE = """#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
"""
FRAGMENT_SHADER_SOURCE = """#version 330 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
"""
POSTPROCESS_VERTEX_SHADER_SOURCE = """#version 330 core
layout (location = 0) in vec2 position;
layout (location = 1) in vec2 inTexCoord;
out vec2 texCoord;
void main(){
texCoord = inTexCoord;
gl_Position = vec4(position.x, position.y, 0.0f, 1.0f);
}
"""
POSTPROCESS_FRAGMENT_SHADER_SOURCE = """#version 330 core
out vec4 fragmentColor;
in vec2 texCoord;
// notice the sampler
uniform sampler2DMS screencapture;
uniform int viewport_width;
uniform int viewport_height;
void main(){
// texelFetch requires a vec of ints for indexing (since we're indexing pixel locations)
// texture coords is range [0, 1], we need range [0, viewport_dim].
// texture coords are essentially a percentage, so we can multiply text coords by total size
ivec2 vpCoords = ivec2(viewport_width, viewport_height);
vpCoords.x = int(vpCoords.x * texCoord.x);
vpCoords.y = int(vpCoords.y * texCoord.y);
// do a simple average since this is just a demo
vec4 sample1 = texelFetch(screencapture, vpCoords, 0);
vec4 sample2 = texelFetch(screencapture, vpCoords, 1);
vec4 sample3 = texelFetch(screencapture, vpCoords, 2);
vec4 sample4 = texelFetch(screencapture, vpCoords, 3);
fragmentColor = vec4(sample1 + sample2 + sample3 + sample4) / 4.0f;
}
"""
def main():
width = 800
height = 600
glfw.init()
glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 3)
glfw.window_hint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.window_hint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE)
window = glfw.create_window(width, height, "OpenglContext", None, None)
if not window:
print("failed to create window")
sys.exit(-1)
glfw.make_context_current(window);
## Not needed for python.
## if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
## {
## std::cerr << "failed to initialize glad with processes " << std::endl;
## exit(-1);
## }
glfw.set_input_mode(window, glfw.CURSOR, glfw.CURSOR_DISABLED)
samples = 4
quadVerts = np.array([
-1.0, -1.0, 0.0, 0.0,
-1.0, 1.0, 0.0, 1.0,
1.0, -1.0, 1.0, 0.0,
1.0, -1.0, 1.0, 0.0,
-1.0, 1.0, 0.0, 1.0,
1.0, 1.0, 1.0, 1.0
], dtype=np.float32)
postVAO = glGenVertexArrays(1)
glBindVertexArray(postVAO)
sizeof_float = ctypes.sizeof(ctypes.c_float) # Complicated way of saying 4
postVBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, postVBO)
glBufferData(GL_ARRAY_BUFFER, quadVerts.nbytes, quadVerts.ctypes._as_parameter_, GL_STATIC_DRAW)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof_float, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof_float, ctypes.c_void_p(2 * sizeof_float))
glEnableVertexAttribArray(1)
glBindVertexArray(0)
msaaFB = glGenFramebuffers(1)
glBindFramebuffer(GL_FRAMEBUFFER, msaaFB); # bind both read/write to the target framebuffer
texMutiSampleColor = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor)
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGB, width, height, GL_TRUE)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor, 0)
glBindFramebuffer(GL_FRAMEBUFFER, 0)
# vertex shader
vertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(vertexShader, VERTEX_SHADER_SOURCE)
glCompileShader(vertexShader)
# check for shader compile errors
# fragment shader
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE)
glCompileShader(fragmentShader)
# check for shader compile errors
# link shaders
shaderProgram = glCreateProgram()
glAttachShader(shaderProgram, vertexShader)
glAttachShader(shaderProgram, fragmentShader)
glLinkProgram(shaderProgram)
# check for linking errors
glDeleteShader(vertexShader)
glDeleteShader(fragmentShader)
#postprocess vertex shader
postProcessVertexShader = glCreateShader(GL_VERTEX_SHADER)
glShaderSource(postProcessVertexShader, POSTPROCESS_VERTEX_SHADER_SOURCE)
glCompileShader(postProcessVertexShader)
# check for shader compile errors
# postprocess fragment shader
postProcessFragmentShader = glCreateShader(GL_FRAGMENT_SHADER)
glShaderSource(postProcessFragmentShader, POSTPROCESS_FRAGMENT_SHADER_SOURCE)
glCompileShader(postProcessFragmentShader)
# check for shader compile errors
# link shaders
postProcessShaderProgram = glCreateProgram()
glAttachShader(postProcessShaderProgram, postProcessVertexShader)
glAttachShader(postProcessShaderProgram, postProcessFragmentShader)
glLinkProgram(postProcessShaderProgram)
# check for linking errors
glDeleteShader(postProcessVertexShader)
glDeleteShader(postProcessFragmentShader)
glUseProgram(postProcessShaderProgram)
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "screencapture"), 0)
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "viewport_width"), width)
glUniform1i(glGetUniformLocation(postProcessShaderProgram, "viewport_height"), height)
vertices = np.array([
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0,
0.0, 0.5, 0.0
], dtype=np.float32)
VAO = glGenVertexArrays(1)
VBO = glGenBuffers(1)
glBindVertexArray(VAO)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices.ctypes._as_parameter_, GL_STATIC_DRAW)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof_float, ctypes.c_void_p(0))
glEnableVertexAttribArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
use_msaa = True
while not glfw.window_should_close(window):
if glfw.get_key(window, glfw.KEY_ESCAPE) == glfw.PRESS:
glfw.set_window_should_close(window, True)
if glfw.get_key(window, glfw.KEY_R) == glfw.PRESS:
use_msaa = True
if glfw.get_key(window, glfw.KEY_T) == glfw.PRESS:
use_msaa = False
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
if use_msaa:
glBindFramebuffer(GL_FRAMEBUFFER, msaaFB)
glClearColor(0.0, 0.0, 0.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT)
# draw our first triangle
glUseProgram(shaderProgram)
glBindVertexArray(VAO)
glDrawArrays(GL_TRIANGLES, 0, 3)
glBindVertexArray(0)
if use_msaa:
glBindFramebuffer(GL_FRAMEBUFFER, 0)
glUseProgram(postProcessShaderProgram)
glActiveTexture(GL_TEXTURE0)
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texMutiSampleColor)
glBindVertexArray(postVAO)
glDrawArrays(GL_TRIANGLES, 0, 6)
glBindVertexArray(0)
glfw.swap_buffers(window)
glfw.poll_events()
glfw.terminate()
# cleanup
if __name__ == "__main__":
main()
I eventually hope to colorize an image based on 3 1d samplers. I wrote this quick program to test if I could map the red channel of a texture to itself, a so called linear mapping.
Right now the code is showing a blank screen, despite all of my error checking in the program, shader, and general execution. When I don't perform the mapping the texture renders as expected.
I am on a GeForce Ti 550, targeting Windows.
The method was largely inspired from: http://www.arcsynthesis.org/gltut/Texturing/Tutorial%2014.html
Make Texture and Sampler
glActiveTexture(GL_TEXTURE1);
glGenTextures(1,lut);
glBindTexture(GL_TEXTURE_1D,lut[0]);
unsigned char* linear = new unsigned char[256];//should be a 1->1 mapping
for (int i = 0 ;i < 256;i++)
{
linear[i] = i;
}
glTexImage1D(GL_TEXTURE_1D, 0, GL_R8, 256, 0,GL_RED, GL_UNSIGNED_BYTE, linear);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAX_LEVEL, 0);
glBindTexture(GL_TEXTURE_1D, 0);
delete linear;
glGenSamplers(1,sampler);
glSamplerParameteri(sampler[0], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(sampler[0], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(sampler[0], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glE();// no errors
Make the program, also no errors
const char *vsrc1 =
"attribute vec2 vecPosIn;\n"
"attribute vec4 texPosIn;\n"
"varying vec4 texPosOut;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(vecPosIn, 0.0, 1.0);\n"
"texPosOut = texPosIn;\n"
"}\n";
GLint vsH = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vsH,1,&vsrc1,NULL);
glCompileShader(vsH);
shaderCheck(vsH);
glE();
const char *fsrc1 =
"uniform sampler2D tex0;\n"
"uniform sampler1D tex1;\n"
"varying vec4 texPosOut;\n"
"void main(void)\n"
"{\n"
//" gl_FragColor = texture2D(tex0, texPosOut.st);\n" //ignores texture and does what I expect
" float red = texture2D(tex0, texPosOut.st).r;\n"
" gl_FragColor = texture1D(tex1, red);\n"
"}\n";
GLint fsH = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fsH,1,&fsrc1,NULL);
glCompileShader(fsH);
shaderCheck(fsH);
glE();
//Bind
programHandle = glCreateProgram();
glBindAttribLocation(programHandle,0,"vecPosIn");
glBindAttribLocation(programHandle,1,"texPosIn");
glBindAttribLocation(programHandle,2,"texPosOut");
glE();
//Link
glAttachShader( programHandle, vsH );
glAttachShader( programHandle, fsH );
glLinkProgram( programHandle );
programCheck(programHandle);
glE();
//Set render() invariants
glUseProgram( programHandle );
GLuint idk = glGetUniformLocation(programHandle, "tex1");
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D,lut[0]);
glUniform1i(idk,0);
glBindTexture(GL_TEXTURE_1D,0);
glUseProgram( 0 );
glE();
//Pack static data into a VAO
float vecData[] = {
-1, 1,
-1,-1,
1, 1,
-1,-1,
1,-1,
1, 1
};
float texData[] = {
0,1,
0,0,
1,1,
0,0,
1,0,
1,1
};
vboHandles=(GLuint*)malloc(sizeof(int)*2);
glGenBuffers(2,vboHandles);
GLuint vecBuf=vboHandles[0];
GLuint texBuf=vboHandles[1];
glBindBuffer(GL_ARRAY_BUFFER, vecBuf);
glBufferData(GL_ARRAY_BUFFER, 8*2 * sizeof(GLfloat), vecData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, texBuf);
glBufferData(GL_ARRAY_BUFFER, 8*2 * sizeof(GLfloat), texData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glE();
glGenVertexArrays( 1, &vaoHandle );
glBindVertexArray(vaoHandle);
glEnableVertexAttribArray(0); // Vertex position
glEnableVertexAttribArray(1); // Vertex color
glBindBuffer(GL_ARRAY_BUFFER, vecBuf);
glVertexAttribPointer( 0, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL );
glBindBuffer(GL_ARRAY_BUFFER, texBuf);
glVertexAttribPointer( 1, 2, GL_FLOAT, GL_FALSE, 0, (GLubyte *)NULL ); //2 attribute per vertex
glBindBuffer(GL_ARRAY_BUFFER,0);
glBindVertexArray(0);
glE();
Render Function
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glE();
//Bind
glUseProgram(programHandle);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,textures[frame]);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D,lut[0]);
GLuint idk = glGetUniformLocation(programHandle, "tex1");
glUniform1i(idk,0);
glBindSampler(0,sampler[0]);glE();
glE();
//Draw
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES,0,8);
glBindVertexArray(0);
glE();
//Unbind
glActiveTexture(GL_TEXTURE1);
glBindSampler(0,0);
glBindTexture(GL_TEXTURE_1D,0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,0);
glUseProgram(0);
glE();
//DumpFrame
glFlush();
glFinish();
glE();
You are setting
glUniform1i(idk,0);
so you tell the GL to use texture unit 0 to sample the "tex1" 1D texture, which is just invalid as you have a 2D texture bound there.
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);