Related
Is there some way to get OpenGL ES 3.0 to broadcast the value of a single-output fragment shader to all active (as per glDrawBuffers()) FBO color attachments?
If possible I'd like to keep my shaders more-or-less as-is and avoid the re-write required by multiple layout'd outputs:
layout( location = 0 ) out vec4 out_color0;
layout( location = 1 ) out vec4 out_color1;
layout( location = 2 ) out vec4 out_color2;
layout( location = 3 ) out vec4 out_color3;
void main()
{
out_color0 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color1 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color2 = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color3 = vec4( 1.0, 0.2, 0.0, 1.0 );
}
...or an output array:
out vec4 out_color[4];
void main()
{
out_color[0] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[1] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[2] = vec4( 1.0, 0.2, 0.0, 1.0 );
out_color[3] = vec4( 1.0, 0.2, 0.0, 1.0 );
}
Here's the program I'm using for testing, it (tries) to draw a red triangle to all four FBO attachments & then blits the 3rd attachment to the default framebuffer:
#include <glad/glad.h>
#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <cstdlib>
#include <cstdarg>
#include <iostream>
#include <vector>
struct Program
{
static GLuint Load( const char* shader, ... )
{
const GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
AttachShader( prog, va_arg( args, GLenum ), shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
std::exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
const GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = 1 + R"GLSL(
#version 300 es
void main()
{
const vec2 verts[3] = vec2[3]
(
vec2( -0.5, -0.5 ),
vec2( 0.5, -0.5 ),
vec2( 0.0, 0.5 )
);
gl_Position = vec4( verts[ gl_VertexID ], 0.0, 1.0 );
}
)GLSL";
const char* frag = 1 + R"GLSL(
#version 300 es
precision mediump float;
out vec4 out_color;
void main()
{
out_color = vec4( 1.0, 0.2, 0.0, 1.0 );
}
)GLSL";
int main( int argc, char** argv )
{
glfwSetErrorCallback( []( int err, const char* desc )
{
std::cerr << "GLFW error: " << desc << std::endl;
} );
if( !glfwInit() )
return EXIT_FAILURE;
glfwWindowHint( GLFW_CLIENT_API, GLFW_OPENGL_ES_API );
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 3 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 0 );
glfwWindowHint( GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API );
GLFWwindow* window = glfwCreateWindow( 640, 480, "GLFW", NULL, NULL );
if( nullptr == window )
return EXIT_FAILURE;
glfwMakeContextCurrent( window );
glfwSwapInterval( 1 );
gladLoadGLES2Loader( (GLADloadproc)glfwGetProcAddress );
const GLuint prog = Program::Load( vert, GL_VERTEX_SHADER, frag, GL_FRAGMENT_SHADER, NULL );
glUseProgram( prog );
// init framebuffer attachments
std::vector< GLuint > textures( 4, 0 );
glGenTextures( 4, textures.data() );
for( size_t i = 0; i < textures.size(); ++ i )
{
glBindTexture( GL_TEXTURE_2D, textures[i] );
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, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr );
}
GLuint rbDepth = 0;
glGenRenderbuffers(1, &rbDepth );
glBindRenderbuffer( GL_RENDERBUFFER, rbDepth );
glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 32, 32 );
// init FBO
GLuint fbo = 0;
glGenFramebuffers( 1, &fbo );
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
for( size_t i = 0; i < textures.size(); ++ i )
{
glFramebufferTexture2D( GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0 );
}
glFramebufferRenderbuffer( GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbDepth );
if( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus( GL_FRAMEBUFFER ) )
{
std::cerr << "Incomplete framebuffer" << std::endl;
std::exit( EXIT_FAILURE );
}
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
// render to FBO
glBindFramebuffer( GL_FRAMEBUFFER, fbo );
GLenum bufs[] =
{
GL_COLOR_ATTACHMENT0 + 0,
GL_COLOR_ATTACHMENT0 + 1,
GL_COLOR_ATTACHMENT0 + 2,
GL_COLOR_ATTACHMENT0 + 3,
};
glDrawBuffers( 4, bufs );
glViewport( 0, 0, 32, 32 );
glClearColor( 0.0f, 0.6f, 1.0f, 1.f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glDrawArrays( GL_TRIANGLES, 0, 3 );
// switch back to default framebuffer & clear it with non-black color
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
GLenum defaultBuf = GL_BACK;
glDrawBuffers( 1, &defaultBuf );
glClearColor( 1.0f, 0.0f, 1.0f, 1.f );
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
// blit a color attachment to the default framebuffer
glBindFramebuffer( GL_READ_FRAMEBUFFER, fbo );
glReadBuffer( GL_COLOR_ATTACHMENT0 + 2 );
glBindFramebuffer( GL_DRAW_FRAMEBUFFER, 0 );
glBlitFramebuffer( 0, 0, 32, 32, 0, 0, 640, 480, GL_COLOR_BUFFER_BIT, GL_LINEAR );
glfwSwapBuffers( window );
}
glfwMakeContextCurrent( NULL );
glfwDestroyWindow( window );
glfwTerminate();
return EXIT_SUCCESS;
}
On this Windows 10 machine using a recent-ish ANGLE build I get the blue clear color but no triangle ("undefined") for the 3rd attachment:
The first attachment is fine:
No such functionality exists in the API:
3) Should we support broadcast from gl_FragColor to all gl_FragData[x]
or should it be synonymous with gl_FragData[0]?
DISCUSSION: With NV_draw_buffers, writing to gl_FragColor writes to all
the enabled draw buffers (ie broadcast). In OpenGL ES 3.0 when using
ESSL 1.0, gl_FragColor is equivalent to writing a single output to
gl_FragData[0] and multiple outputs are not possible. When using ESSL 3.0,
only user-defined out variables may be used.
If broadcast is supported, some implementations may have to replace
writes to gl_FragColor with replicated writes to all possible gl_FragData
locations when this extension is enabled.
RESOLVED: Writes to gl_FragColor are broadcast to all enabled color
buffers. ES 3.0 using ESSL 1.0 doesn't support broadcast because
ESSL 1.0 was not extended to have multiple color outputs (but that is
what this extension adds). ESSL 3.0 doesn't support the broadcast because
it doesn't have the gl_FragColor variable at all, and only has user-
defined out variables. This extension extends ESSL 1.0 to have multiple
color outputs. Broadcasting from gl_FragColor to all enabled color
buffers is the most consistent with existing draw buffer extensions to
date (both NV_draw_buffers and desktop GL).
I'm new to OpenGl and I was working on texturing. I want to draw one image on three sides and another image on other three sides of cube. I'm unable to do it. I want to know at what point in my code is cube being drawn on window?
This is my code:
#include "06_texturing.hpp"
#include "texture.hpp"
GLuint shaderProgram;
GLuint vbo[2], vao[2];
GLuint tex;
glm::mat4 rotation_matrix;
glm::mat4 projection_matrix;
glm::mat4 c_rotation_matrix;
glm::mat4 lookat_matrix;
glm::mat4 model_matrix;
glm::mat4 view_matrix;
glm::mat4 modelview_matrix;
glm::mat3 normal_matrix;
GLuint uModelViewMatrix;
GLuint viewMatrix;
GLuint normalMatrix;
//-----------------------------------------------------------------
//6 faces, 2 triangles/face, 3 vertices/triangle
const int num_vertices = 36;
glm::vec4 texCoordinates[8];
//Eight vertices in homogenous coordinates
glm::vec4 positions[8] = {
glm::vec4(-0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, -0.5, -0.5, 1.0),
glm::vec4(-0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, -0.5, -0.5, 1.0)
};
glm::vec4 normals[8] = {
glm::vec4(-0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, 0.5, 0.5, 1.0),
glm::vec4(0.5, -0.5, 0.5, 1.0),
glm::vec4(-0.5, -0.5, -0.5, 1.0),
glm::vec4(-0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, 0.5, -0.5, 1.0),
glm::vec4(0.5, -0.5, -0.5, 1.0)
};
//RGBA colors
glm::vec4 colors[8] = {
glm::vec4(0.0, 0.0, 0.0, 1.0),
glm::vec4(1.0, 0.0, 0.0, 1.0),
glm::vec4(1.0, 1.0, 0.0, 1.0),
glm::vec4(0.0, 1.0, 0.0, 1.0),
glm::vec4(0.0, 0.0, 1.0, 1.0),
glm::vec4(1.0, 0.0, 1.0, 1.0),
glm::vec4(1.0, 1.0, 1.0, 1.0),
glm::vec4(0.0, 1.0, 1.0, 1.0)
};
glm::vec2 t_coords[4] = {
glm::vec2( 0.0, 0.0),
glm::vec2( 0.0, 1.0),
glm::vec2( 1.0, 0.0),
glm::vec2( 1.0, 1.0)
};
glm::vec4 color(0.6, 0.6, 0.6, 1.0);
glm::vec4 black(0.1, 0.1, 0.1, 1.0);
glm::vec4 white(0.2, 0.7, 0.7, 1.0);
glm::vec4 red(1.0, 0.2, 0.2, 1.0);
glm::vec4 yellow(0.8, 0.8, 0.0, 1.0);
glm::vec4 green(0.2, 0.7, 0.2, 1.0);
glm::vec4 blue(0.2, 0.2, 0.7, 1.0);
int tri_idx=0;
glm::vec4 v_positions[num_vertices];
glm::vec4 v_colors[num_vertices];
glm::vec4 v_normals[num_vertices];
glm::vec2 tex_coords[num_vertices];
// quad generates two triangles for each face and assigns colors to the vertices
void quad(int a, int b, int c, int d, glm::vec4 color)
{
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[a];
v_normals[tri_idx] = normals[a];
tex_coords[tri_idx] = t_coords[1];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[b];
v_normals[tri_idx] = normals[b];
tex_coords[tri_idx] = t_coords[0];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[c];
v_normals[tri_idx] = normals[c];
tex_coords[tri_idx] = t_coords[2];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[a];
v_normals[tri_idx] = normals[a];
tex_coords[tri_idx] = t_coords[1];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[c];
v_normals[tri_idx] = normals[c];
tex_coords[tri_idx] = t_coords[2];
tri_idx++;
v_colors[tri_idx] = color; v_positions[tri_idx] = positions[d];
v_normals[tri_idx] = normals[d];
tex_coords[tri_idx] = t_coords[3];
tri_idx++;
}
// generate 12 triangles: 36 vertices and 36 colors
void colorcube(void)
{
quad( 1, 0, 3, 2, red);
quad( 2, 3, 7, 6, green);
quad( 3, 0, 4, 7, white);
quad( 6, 5, 1, 2, yellow);
quad( 4, 5, 6, 7, black);
quad( 5, 4, 0, 1, blue);
}
//-----------------------------------------------------------------
void initBuffersGL(void)
{
// Load shaders and use the resulting shader program
std::string vertex_shader_file("06_vshader.glsl");
std::string fragment_shader_file("06_fshader.glsl");
std::vector<GLuint> shaderList;
shaderList.push_back(csX75::LoadShaderGL(GL_VERTEX_SHADER, vertex_shader_file));
shaderList.push_back(csX75::LoadShaderGL(GL_FRAGMENT_SHADER, fragment_shader_file));
shaderProgram = csX75::CreateProgramGL(shaderList);
glUseProgram( shaderProgram );
// getting the attributes from the shader program
GLuint vPosition = glGetAttribLocation( shaderProgram, "vPosition" );
GLuint vColor = glGetAttribLocation( shaderProgram, "vColor" );
GLuint vNormal = glGetAttribLocation( shaderProgram, "vNormal" );
GLuint texCoord = glGetAttribLocation( shaderProgram, "texCoord" );
uModelViewMatrix = glGetUniformLocation( shaderProgram, "uModelViewMatrix");
normalMatrix = glGetUniformLocation( shaderProgram, "normalMatrix");
viewMatrix = glGetUniformLocation( shaderProgram, "viewMatrix");
// Load Textures
GLuint tex=LoadTexture("images/all1.bmp",256,256);
GLuint tex2=LoadTexture("images/another.bmp",256,256);
glBindTexture(GL_TEXTURE_2D, tex);
//Ask GL for two Vertex Attribute Objects (vao) , one for the sphere and one for the wireframe
glGenVertexArrays (2, vao);
//Ask GL for two Vertex Buffer Object (vbo)
glGenBuffers (2, vbo);
//Set 0 as the current array to be used by binding it
glBindVertexArray (vao[0]);
//Set 0 as the current buffer to be used by binding it
glBindBuffer (GL_ARRAY_BUFFER, vbo[0]);
colorcube();
//Copy the points into the current buffer
glBufferData (GL_ARRAY_BUFFER, sizeof (v_positions) + sizeof(tex_coords) + sizeof(v_normals), NULL, GL_STATIC_DRAW);
glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(v_positions), v_positions );
glBufferSubData( GL_ARRAY_BUFFER, sizeof(v_positions), sizeof(tex_coords), tex_coords);
glBufferSubData( GL_ARRAY_BUFFER, sizeof(tex_coords)+sizeof(v_positions), sizeof(v_normals), v_normals );
// set up vertex array
//Position
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
//Textures
glEnableVertexAttribArray( texCoord );
glVertexAttribPointer( texCoord, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)) );
//Normal
glEnableVertexAttribArray( vNormal );
glVertexAttribPointer( vNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(v_positions)+sizeof(tex_coords)) );
}
void renderGL(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
rotation_matrix = glm::rotate(glm::mat4(1.0f), glm::radians(xrot), glm::vec3(1.0f,0.0f,0.0f));
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(yrot), glm::vec3(0.0f,1.0f,0.0f));
rotation_matrix = glm::rotate(rotation_matrix, glm::radians(zrot), glm::vec3(0.0f,0.0f,1.0f));
model_matrix = rotation_matrix;
//Creating the lookat and the up vectors for the camera
c_rotation_matrix = glm::rotate(glm::mat4(1.0f), glm::radians(c_xrot), glm::vec3(1.0f,0.0f,0.0f));
c_rotation_matrix = glm::rotate(c_rotation_matrix, glm::radians(c_yrot), glm::vec3(0.0f,1.0f,0.0f));
c_rotation_matrix = glm::rotate(c_rotation_matrix, glm::radians(c_zrot), glm::vec3(0.0f,0.0f,1.0f));
glm::vec4 c_pos = glm::vec4(c_xpos,c_ypos,c_zpos, 1.0)*c_rotation_matrix;
glm::vec4 c_up = glm::vec4(c_up_x,c_up_y,c_up_z, 1.0)*c_rotation_matrix;
//Creating the lookat matrix
lookat_matrix = glm::lookAt(glm::vec3(c_pos),glm::vec3(0.0),glm::vec3(c_up));
//creating the projection matrix
projection_matrix = glm::frustum(-1.0, 1.0, -1.0, 1.0, 1.0, 5.0);
view_matrix = projection_matrix*lookat_matrix;
glUniformMatrix4fv(viewMatrix, 1, GL_FALSE, glm::value_ptr(view_matrix));
// Draw the sphere
modelview_matrix = view_matrix*model_matrix;
glUniformMatrix4fv(uModelViewMatrix, 1, GL_FALSE, glm::value_ptr(modelview_matrix));
normal_matrix = glm::transpose (glm::inverse(glm::mat3(modelview_matrix)));
glUniformMatrix3fv(normalMatrix, 1, GL_FALSE, glm::value_ptr(normal_matrix));
// glBindTexture(GL_TEXTURE_2D, tex);
glBindVertexArray (vao[0]);
glDrawArrays(GL_TRIANGLES, 0, num_vertices);
}
int main(int argc, char** argv)
{
//! The pointer to the GLFW window
GLFWwindow* window;
//! Setting up the GLFW Error callback
glfwSetErrorCallback(csX75::error_callback);
//! Initialize GLFW
if (!glfwInit())
return -1;
//We want OpenGL 4.0
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//This is for MacOSX - can be omitted otherwise
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
//We don't want the old OpenGL
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
//! Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(512, 512, "CS475/CS675 Tutorial 6: Texturing a cube", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
//! Make the window's context current
glfwMakeContextCurrent(window);
//Initialize GLEW
//Turn this on to get Shader based OpenGL
glewExperimental = GL_TRUE;
GLenum err = glewInit();
if (GLEW_OK != err)
{
//Problem: glewInit failed, something is seriously wrong.
std::cerr<<"GLEW Init Failed : %s"<<std::endl;
}
//Keyboard Callback
glfwSetKeyCallback(window, csX75::key_callback);
//Framebuffer resize callback
glfwSetFramebufferSizeCallback(window, csX75::framebuffer_size_callback);
// Ensure we can capture the escape key being pressed below
glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE);
//Initialize GL state
csX75::initGL();
initBuffersGL();
// Loop until the user closes the window
while (glfwWindowShouldClose(window) == 0)
{
// Render here
renderGL();
// Swap front and back buffers
glfwSwapBuffers(window);
// Poll for and process events
glfwPollEvents();
}
glfwTerminate();
return 0;
}
I want to change in it to render different images on different sides.
If you want to use 2 completely different textures, in the fragment shader, then you have to bind the textures to 2 different texture units. The texture unit can be set by glActiveTexture:
GLuint tex=LoadTexture("images/all1.bmp",256,256);
GLuint tex2=LoadTexture("images/another.bmp",256,256);
int unit_tex0 = 0; // texture unit 0 and binding point 0
int unit_tex1 = 1; // texture unit 1 and binding point 1
glActiveTexture( GL_TEXTURE0 + unit_tex0 );
glBindTexture(GL_TEXTURE_2D, tex);
glActiveTexture( GL_TEXTURE0 + unit_tex1 );
glBindTexture(GL_TEXTURE_2D, tex2);
Further you have to declare 2 texture samplers in the fragment shader. The texture samplers have to be associated to the texture units. Since GLSL version 4.2 this can be done in the fragment shader by specifying binding points:
#version 420
layout (binding = 0) uniform sampler2D u_texture0;
layout (binding = 1) uniform sampler2D u_texture1;
Alternatively you can assign the texture unit index, to the texture sampler uniform by glUniform1i:
uniform sampler2D u_texture0;
uniform sampler2D u_texture1;
GLuint location_tex0 = glGetUniformLocation( shaderProgram, "u_texture0" );
GLuint location_tex1 = glGetUniformLocation( shaderProgram, "u_texture1" );
glUniform1i( location_tex0, unit_tex0 );
glUniform1i( location_tex1, unit_tex1 );
To distinguish between the sides of the cubes, you can use the built in vertex shader variable gl_VertexID.
Create a flat out variable of type int in the vertex shader and pass the vertex id to the fragment shader:
flat out int vertex_id;
void main()
{
.....
vertex_id = gl_VertexID;
.....
}
In the fragment shader yo can decide which texture you want to use by the id corresponding to the vertex coordinate. Note, you have 36 coordinates, the first 3 sides have the ids form 0 to 17 and the other the ids form 18 to 35:
flat in int vertex_id;
void main()
{
.....
if ( vertex_id < 18 )
fragColor = texture(u_texture0, vertUV);
else
fragColor = texture(u_texture1, vertUV);
.....
}
I am trying to draw a triangle with OpenGL.
My code compiles fine, and does not produce any errors but it still does not do what its supposed to.
I have a vertex shader and a fragment shader and both of them are in the same program.
My code is below:
#include "../../include/sb7.h"
GLuint compile_shaders(void)
{
GLuint vertex_shader;
GLuint fragment_shader;
GLuint program;
// Source code for Vertex Shader
static const GLchar * vertex_shader_source[] =
{
"#version 450 core \n"
" \n"
"void main(void) \n"
"{ \n"
" //Decalre a hardcoded array of positions \n"
" const vec4 vertices[3] = vec4[3](vec4(0.25, -0.25, 0.5, 1.0), \n"
" vec4(-0.25, -0.25, 0.5, 1.0), \n"
" vec4(0.25, 0.25, 0.5, 1.0)); \n"
" //Index into our array using gl_VertexID \n"
" gl_Position = vertices[gl_VertexID]; \n"
"} \n"
};
// Source code for Fragment Shader
static const GLchar * fragment_shader_source[] =
{
"#version 450 core \n"
" \n"
"out vec4 color; \n"
" \n"
"void main(void) \n"
"{ \n"
" color = vec4(0.0, 0.8, 1.0, 1.0); \n"
"} \n"
};
// Create and compiler Vertex Shader
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_source, NULL);
glCompileShader(vertex_shader);
// Create and compiler Fragment Shader
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, fragment_shader_source, NULL);
glCompileShader(fragment_shader);
// Create program, attach shaders to it, and link it
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
// Delete shaders as program has them now
glDeleteShader(vertex_shader);
glDeleteShader(fragment_shader);
return program;
};
class my_application : public sb7::application
{
public:
void startup()
{
rendering_program = compile_shaders();
glCreateVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
}
void shutdown()
{
glDeleteVertexArrays(1, &vertex_array_object);
glDeleteProgram(rendering_program);
glDeleteVertexArrays(1, &vertex_array_object);
}
// Our rendering function
void render(double currentTime)
{
// Sets Colour
static const GLfloat color[] = { 0.0f, 0.2f, 0.0f, 1.0f };
glClearBufferfv(GL_COLOR, 0, color);
// Use program object we created for rendering
glUseProgram(rendering_program);
// Draw one triangle
glDrawArrays(GL_TRIANGLES, 0, 3);
}
private:
GLuint rendering_program;
GLuint vertex_array_object;
};
I am following the OpenGL Superbible, 7th edition.
The same program (with small changes) was also not drawing a point even when I changed the point size and the output was the same screen (full yellow) that I am getting for this.
I have seen similar problems that arise during drawing of triangles but they are all different from what I'm doing.
How do I fix this?
Workin' fine here:
All together:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <cstdarg>
#include <cstdlib>
struct Program
{
static GLuint Load( const char* shader, ... )
{
GLuint prog = glCreateProgram();
va_list args;
va_start( args, shader );
while( shader )
{
const GLenum type = va_arg( args, GLenum );
AttachShader( prog, type, shader );
shader = va_arg( args, const char* );
}
va_end( args );
glLinkProgram( prog );
CheckStatus( prog );
return prog;
}
private:
static void CheckStatus( GLuint obj )
{
GLint status = GL_FALSE;
if( glIsShader(obj) ) glGetShaderiv( obj, GL_COMPILE_STATUS, &status );
if( glIsProgram(obj) ) glGetProgramiv( obj, GL_LINK_STATUS, &status );
if( status == GL_TRUE ) return;
GLchar log[ 1 << 15 ] = { 0 };
if( glIsShader(obj) ) glGetShaderInfoLog( obj, sizeof(log), NULL, log );
if( glIsProgram(obj) ) glGetProgramInfoLog( obj, sizeof(log), NULL, log );
std::cerr << log << std::endl;
exit( EXIT_FAILURE );
}
static void AttachShader( GLuint program, GLenum type, const char* src )
{
GLuint shader = glCreateShader( type );
glShaderSource( shader, 1, &src, NULL );
glCompileShader( shader );
CheckStatus( shader );
glAttachShader( program, shader );
glDeleteShader( shader );
}
};
const char* vert = R"GLSL(
#version 450 core
void main(void)
{
//Decalre a hardcoded array of positions
const vec4 vertices[3] = vec4[3]
(
vec4(0.25, -0.25, 0.5, 1.0),
vec4(-0.25, -0.25, 0.5, 1.0),
vec4(0.25, 0.25, 0.5, 1.0)
);
//Index into our array using gl_VertexID
gl_Position = vertices[gl_VertexID];
}
)GLSL";
const char* frag = R"GLSL(
#version 450 core
out vec4 color;
void main(void)
{
color = vec4(0.0, 0.8, 1.0, 1.0);
}
)GLSL";
int main( int argc, char** argv )
{
glfwInit();
glfwWindowHint( GLFW_CONTEXT_VERSION_MAJOR, 4 );
glfwWindowHint( GLFW_CONTEXT_VERSION_MINOR, 5 );
glfwWindowHint( GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE );
glfwWindowHint( GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE );
GLFWwindow* window = glfwCreateWindow( 640, 480, "51307782", NULL, NULL );
glfwMakeContextCurrent( window );
glewInit();
glfwSwapInterval( 1 );
GLuint rendering_program = Program::Load
(
vert, GL_VERTEX_SHADER,
frag, GL_FRAGMENT_SHADER,
NULL
);
GLuint vertex_array_object = 0;
glCreateVertexArrays( 1, &vertex_array_object );
glBindVertexArray( vertex_array_object );
while( !glfwWindowShouldClose( window ) )
{
glfwPollEvents();
static const GLfloat color[] = { 0.0f, 0.2f, 0.0f, 1.0f };
glClearBufferfv( GL_COLOR, 0, color );
glUseProgram( rendering_program );
glDrawArrays( GL_TRIANGLES, 0, 3 );
glfwSwapBuffers( window );
}
glDeleteVertexArrays( 1, &vertex_array_object );
glDeleteProgram( rendering_program );
glfwDestroyWindow( window );
glfwTerminate();
}
I am using Xcode to write openGL. What I am doing is to draw a circle, a triangle, and a square.
However, I found that my circle only can display on
glutInitDisplayMode(GLUT_RGBA | GLUT_SINGLE);
the triangle and square can only display on glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA | GLUT_SINGLE);
How can i make them display together?
Here is part of my entire code:
#include "Angel.h" //includes gl.h, glut.h and other stuff...
void m_glewInitAndVersion(void); //pre-implementation declaration (could do in header file)
void close(void);
//Mesh 0
GLuint buffer[3];
GLuint VAO[3];
GLuint color_loc;
GLuint program;
const int NumVertices = 4;
// Vertices of a unit cube centered at origin, sides aligned with axes
vec2 points[4] = {
vec2( 0.25, 0.25),
vec2( 0.75, 0.25),
vec2( 0.75, 0.75),
vec2( 0.25, 0.75)
};
vec2 points2[3]={
vec2(-1,-1),
vec2(0,-1),
vec2(0,-0.7)};
// RGBA colors
vec4 blue_opaque = vec4( 0.0, 0.0, 1.0, 1.0 );
vec4 red_opaque = vec4(1.0, 0.0, 0.0, 1.0);
//----------------------------------------------------------------------------
// OpenGL initialization
void
init()
{
glClearColor( 1.0, 1.0, 1.0, 1.0 );
// glColor3f(1.0, 0.0, 0.0);
// glMatrixMode(GL_PROJECTION);
// glLoadIdentity();
// gluOrtho2D(-3.5, 3.5, -3.5, 3.5);
// Create and initialize a buffer object
glGenBuffers( 2, buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer[0] );
glBufferData( GL_ARRAY_BUFFER, sizeof(points), points, GL_STATIC_DRAW );
// Load shaders and use the resulting shader program
program = InitShader( "vshader00_v150.glsl", "fshader00_v150.glsl" );
glUseProgram( program );
// set up vertex arrays
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
//Set up VAO
glGenVertexArrays(2,VAO);
glBindVertexArray(VAO[0]);
glBindBuffer(GL_ARRAY_BUFFER,buffer[0]);
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
color_loc = glGetUniformLocation(program, "color");
//triangle
// glBindVertexArray(VAO[1]);
// glBindBuffer(GL_ARRAY_BUFFER, buffer[1]);
// glBufferData(GL_ARRAY_BUFFER, sizeof(points2), points2, GL_STATIC_DRAW);
// glUseProgram(program);
// glEnableVertexAttribArray(vPosition);
// glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0) );
}
//----------------------------------------------------------------------------
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT );
// const float PI=3.14159;
// glBegin(GL_TRIANGLE_FAN);
// All triangles fan out starting with this point
// glVertex2f (0.0,0.0);
// for (int i = 0; i <=361; i++)
// {
// glColor3f(float(rand())/float(RAND_MAX),
// float(rand())/float(RAND_MAX),
// float(rand())/float(RAND_MAX));
// glVertex2f(2.0*cos(i*PI/180), 2.0*sin(i*PI/180));
// }
// glEnd();
glBindVertexArray(VAO[0]);
glDrawArrays( GL_TRIANGLE_FAN, 0, NumVertices );
glUseProgram(program);
glUniform4fv(color_loc, 1, blue_opaque);
// glBindVertexArray(VAO[1]);
// glDrawArrays( GL_TRIANGLE_FAN, 0, 3);
// glUseProgram(program);
// glUniform4fv(color_loc, 1, red_opaque);
glFlush();
}
int main( int argc, char **argv )
{
glutInit( &argc, argv );
#ifdef __APPLE__
glutInitDisplayMode(GLUT_3_2_CORE_PROFILE|GLUT_RGBA | GLUT_SINGLE);
#else
glutInitDisplayMode( GLUT_RGBA | GLUT_SINGLE);
#endif
glutInitWindowSize( 500, 500 );
glutCreateWindow( "CS 432 Hello World" );
m_glewInitAndVersion();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutWMCloseFunc(close);
glutMainLoop();
return 0;
}
Your circle code doesn't work with GLUT_3_2_CORE_PROFILE because glBegin, glColor3f, glVertex2f and glEnd were removed in OpenGL 3, so OpenGL 3.2 (or later) doesn't have them.
I'm not sure exactly why your triangle and square code doesn't work without GLUT_3_2_CORE_PROFILE, but consider that VAOs were added in OpenGL 3, and when you don't specify GLUT_3_2_CORE_PROFILE, you get a version before 3.
Pick a version and stick with it.
I simply want to map images as textures to the faces of a cube and display. Instead of having my images on it, the cube is totally black. My images are both 64x64 jpg's.
My application code is below. Originally it was a program that generated 2 checkerboard textures, displayed 1 at a time on all faces of the cube, allowing the user to switch between them. Instead of a checkerboard on all faces, I want an image. I've commented out their texture generation and texture loading code, replacing it with, most importantly, ilutGLLoadImage() (from DevIL): it's supposed to kill most image-texture loading birds with one stone. This happens in init(). The only console output is "1,2" (from my cout), which implies that the images were loaded and given valid texture ID's. Why is the cube black?
Application code (init() is a good place to start looking):
#include "Angel.h"
#include <IL\config.h>
#include <IL\ilut_config.h>
#include <IL\il.h>
#include <IL\ilu.h>
#include <IL\ilut.h>
#include <iostream>
using namespace std;
const int NumTriangles = 12; // (6 faces)(2 triangles/face)
const int NumVertices = 3 * NumTriangles;
const int TextureSize = 64;
typedef Angel::vec4 point4;
typedef Angel::vec4 color4;
// Texture objects and storage for texture image
//GLuint textures[2];
GLuint tex1;
GLuint tex2;
//GLubyte image[TextureSize][TextureSize][3];
//GLubyte image2[TextureSize][TextureSize][3];
// Vertex data arrays
point4 points[NumVertices];
//color4 quad_colors[NumVertices];
vec2 tex_coords[NumVertices];
// Array of rotation angles (in degrees) for each coordinate axis
enum { Xaxis = 0, Yaxis = 1, Zaxis = 2, NumAxes = 3 };
int Axis = Xaxis;
GLfloat Theta[NumAxes] = { 0.0, 0.0, 0.0 };
GLuint theta;
//----------------------------------------------------------------------------
int Index = 0;
void
quad( int a, int b, int c, int d )
{
point4 vertices[8] = {
point4( -0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, 0.5, 0.5, 1.0 ),
point4( 0.5, -0.5, 0.5, 1.0 ),
point4( -0.5, -0.5, -0.5, 1.0 ),
point4( -0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, 0.5, -0.5, 1.0 ),
point4( 0.5, -0.5, -0.5, 1.0 )
};
color4 colors[8] = {
color4( 0.0, 0.0, 0.0, 1.0 ), // black
color4( 1.0, 0.0, 0.0, 1.0 ), // red
color4( 1.0, 1.0, 0.0, 1.0 ), // yellow
color4( 0.0, 1.0, 0.0, 1.0 ), // green
color4( 0.0, 0.0, 1.0, 1.0 ), // blue
color4( 1.0, 0.0, 1.0, 1.0 ), // magenta
color4( 0.0, 1.0, 1.0, 1.0 ), // white
color4( 1.0, 1.0, 1.0, 1.0 ) // cyan
};
// bottom-left texture coord
// quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
// top-left texture coord
// quad_colors[Index] = colors[a];
points[Index] = vertices[b];
tex_coords[Index] = vec2( 0.0, 1.0 );
Index++;
// top-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
// bottom-left
// quad_colors[Index] = colors[a];
points[Index] = vertices[a];
tex_coords[Index] = vec2( 0.0, 0.0 );
Index++;
// top-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[c];
tex_coords[Index] = vec2( 1.0, 1.0 );
Index++;
// bottom-right
// quad_colors[Index] = colors[a];
points[Index] = vertices[d];
tex_coords[Index] = vec2( 1.0, 0.0 );
Index++;
}
//----------------------------------------------------------------------------
void
colorcube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
//----------------------------------------------------------------------------
void
init()
{
colorcube();
ILuint devilError;
ilInit();
iluInit();
ilutInit();
devilError = ilGetError();
if (devilError != IL_NO_ERROR) {
printf ("Devil Error (ilInit: %s\n", iluErrorString(devilError));
exit (2);
}
ilutRenderer(ILUT_OPENGL);
GLuint openglID, openglError;
tex1 = ilutGLLoadImage("test1.jpg");
tex2 = ilutGLLoadImage("test2.jpg");
cout << tex1 << "," << tex2 << endl;
devilError = ilGetError();
if (devilError != IL_NO_ERROR) {
printf ("Error: %s\n", iluGetString (devilError));
exit (2);
}
if (openglError != GL_NO_ERROR) {
printf ("Opengl Error (ilutGLBindTexImage): %s\n", gluGetString (openglError));
exit (2);
}
// // Create a checkerboard pattern
// for ( int i = 0; i < 64; i++ ) {
// for ( int j = 0; j < 64; j++ ) {
// GLubyte c = (((i & 0x8) == 0) ^ ((j & 0x8) == 0)) * 255;
// image[i][j][0] = c;
// image[i][j][1] = c;
// image[i][j][2] = c;
// image2[i][j][0] = c;
// image2[i][j][1] = 0;
// image2[i][j][2] = c;
// }
// }
//
// // Initialize texture objects
//
// // Get unused texture identifiers
// glGenTextures( 2, textures );
//
glBindTexture( GL_TEXTURE_2D, tex1 );
//
// // Specify that 'image' is to be used as a two-dimensional texture
// glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
// GL_RGB, GL_UNSIGNED_BYTE, image );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
//
glBindTexture( GL_TEXTURE_2D, tex2 );
// glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, TextureSize, TextureSize, 0,
// GL_RGB, GL_UNSIGNED_BYTE, image2 );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST );
// glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glActiveTexture( GL_TEXTURE0 );
// Set the current texture object
glBindTexture( GL_TEXTURE_2D, tex1 );
// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
// Create and initialize a buffer object
GLuint buffer;
glGenBuffers( 1, &buffer );
glBindBuffer( GL_ARRAY_BUFFER, buffer );
// glBufferData( GL_ARRAY_BUFFER,
// sizeof(points) + sizeof(quad_colors) + sizeof(tex_coords),
// NULL, GL_STATIC_DRAW );
glBufferData( GL_ARRAY_BUFFER,
sizeof(points) + sizeof(tex_coords),
NULL, GL_STATIC_DRAW );
// Specify an offset to keep track of where we're placing data in our
// vertex array buffer. We'll use the same technique when we
// associate the offsets with vertex attribute pointers.
GLintptr offset = 0;
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(points), points );
offset += sizeof(points);
// glBufferSubData( GL_ARRAY_BUFFER, offset,
// sizeof(quad_colors), quad_colors );
// offset += sizeof(quad_colors);
glBufferSubData( GL_ARRAY_BUFFER, offset, sizeof(tex_coords), tex_coords );
// Load shaders and use the resulting shader program
GLuint program = InitShader( "vshader71.glsl", "fshader71.glsl" );
glUseProgram( program );
// set up vertex arrays
offset = 0;
GLuint vPosition = glGetAttribLocation( program, "vPosition" );
glEnableVertexAttribArray( vPosition );
glVertexAttribPointer( vPosition, 4, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
offset += sizeof(points);
// GLuint vColor = glGetAttribLocation( program, "vColor" );
// glEnableVertexAttribArray( vColor );
// glVertexAttribPointer( vColor, 4, GL_FLOAT, GL_FALSE, 0,
// BUFFER_OFFSET(offset) );
// offset += sizeof(quad_colors);
// Pass the texture coordinates as a vertex attribute with the identifier 'vTextCoord'
GLuint vTexCoord = glGetAttribLocation( program, "vTexCoord" );
glEnableVertexAttribArray( vTexCoord );
glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, GL_FALSE, 0,
BUFFER_OFFSET(offset) );
// Set the value of the fragment shader texture sampler variable
// ("texture") to the the appropriate texture unit. In this case,
// zero, for GL_TEXTURE0 which was previously set by calling
// glActiveTexture().
glUniform1i( glGetUniformLocation(program, "texture"), 0 );
theta = glGetUniformLocation( program, "theta" );
glEnable( GL_DEPTH_TEST );
glClearColor( 1.0, 1.0, 1.0, 1.0 );
}
void
display( void )
{
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glUniform3fv( theta, 1, Theta );
glDrawArrays( GL_TRIANGLES, 0, NumVertices );
glutSwapBuffers();
}
//----------------------------------------------------------------------------
void
mouse( int button, int state, int x, int y )
{
if ( state == GLUT_DOWN ) {
switch( button ) {
case GLUT_LEFT_BUTTON: Axis = Xaxis; break;
case GLUT_MIDDLE_BUTTON: Axis = Yaxis; break;
case GLUT_RIGHT_BUTTON: Axis = Zaxis; break;
}
}
}
//----------------------------------------------------------------------------
void
idle( void )
{
Theta[Axis] += 0.01;
if ( Theta[Axis] > 360.0 ) {
Theta[Axis] -= 360.0;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
void
keyboard( unsigned char key, int mousex, int mousey )
{
switch( key ) {
case 033: // Escape Key
case 'q': case 'Q':
exit( EXIT_SUCCESS );
break;
case '1':
glBindTexture( GL_TEXTURE_2D, tex1 );
break;
case '2':
glBindTexture( GL_TEXTURE_2D, tex2 );
break;
}
glutPostRedisplay();
}
//----------------------------------------------------------------------------
int
main( int argc, char **argv )
{
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
glutInitWindowSize( 512, 512 );
glutInitContextVersion( 3, 2 );
glutInitContextProfile( GLUT_CORE_PROFILE );
glutCreateWindow( "Texture Cube" );
glewExperimental = GL_TRUE;
glewInit();
init();
glutDisplayFunc( display );
glutKeyboardFunc( keyboard );
glutMouseFunc( mouse );
glutIdleFunc( idle );
glutMainLoop();
return 0;
}
Vertex shader:
#version 150
in vec4 vPosition;
in vec2 vTexCoord;
out vec4 color;
out vec2 texCoord;
uniform vec3 theta;
void main()
{
const float DegreesToRadians = 3.14159265 / 180.0;
vec3 c = cos( DegreesToRadians * theta );
vec3 s = sin( DegreesToRadians * theta );
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, -s.x, 0.0,
0.0, s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0);
mat4 ry = mat4( c.y, 0.0, s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
-s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
// Workaround for bug in ATI driver
ry[1][0] = 0.0;
ry[1][1] = 1.0;
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
// Workaround for bug in ATI driver
rz[2][2] = 1.0;
texCoord = vTexCoord;
gl_Position = rz * ry * rx * vPosition;
}
Fragment shader:
#version 150
in vec2 texCoord;
out vec4 fColor;
uniform sampler2D texture;
void main()
{
fColor = texture2D( texture, texCoord );
}