Geometry shader doesn't emit geometry - c++

I am setting the following pipeline:
Vertex shader gets as input 4 vertices to draw as full screen quad with triangle strip :
Vertex Shader:
#version 420 core
layout(location = 0) in vec4 position;
out gl_PerVertex
{
vec4 gl_Position;
}
;
void main()
{
gl_Position = position;
}
Then I want to do some work on them in geometry shader .But for now I just try to emit the same vertices as triangle strip from the shader just to make sure it work ok.
Geom Shader
#version 420 core
layout(invocations = 1,triangles) in;
layout(triangle_strip, max_vertices =4) out;
out gl_PerVertex
{
vec4 gl_Position;
};
void main()
{
gl_Position = vec4( 1.0, 1.0, 0.0, 1.0 );
EmitVertex();
gl_Position = vec4(-1.0, 1.0, 0.0, 1.0 );
EmitVertex();
gl_Position = vec4( 1.0,-1.0, 0.0, 1.0 );
EmitVertex();
gl_Position = vec4(-1.0,-1.0, 0.0, 1.0 );
EmitVertex();
EndPrimitive();
}
And the fragment shader:
#version 420 core
layout(binding=0) uniform sampler2D COLOR_MAP_0;
out vec4 OUTPUT;
void main(void) {
OUTPUT = vec4(1,0,0,1);
}
The client side setup is like this:
glm::vec4 va[4] ={glm::vec4(1.0, 1.0, 0.0, 1.0),glm::vec4(-1.0, 1.0, 0.0, 1.0),glm::vec4( 1.0,-1.0, 0.0, 1.0),glm::vec4(-1.0,-1.0, 0.0, 1.0)};
auto ss = sizeof(va);
glGenVertexArrays(1,&_dummyVao);
glBindVertexArray(_dummyVao);
glGenBuffers(1,&_dummyPoinBuff);
glBindBuffer(GL_ARRAY_BUFFER, _dummyPoinBuff);
glBufferData(GL_ARRAY_BUFFER, ss, &va[0], GL_STATIC_DRAW);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, ((GLubyte *)NULL + (0)));
glEnableVertexAttribArray(0);
glBindVertexArray(0);
The draw call:
glBindVertexArray(_dummyVao);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
The weird thing is that it doesn't work!The output is empty.If I switch to emit points instead ,it does emit them.The vertex data is 100% correct.it draws the quad ok if I detach the geometry shader.What can be possibly wrong here?
UPDATE:
This variation does work.
const vec2 vert_data[4] = vec2[](
vec2(-1.0, 1.0),
vec2(-1.0, -1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0)
);
for(int i=0; i<4; i++)
{
gl_Position = vec4( vert_data[i].xy,0,1);///gl_Position;
EmitVertex();
}
EndPrimitive();
Redclare of inputs / outputs in geometry shader still didn't help:
in gl_PerVertex
{
vec4 gl_Position;
} gl_in[];
out gl_PerVertex
{
vec4 gl_Position;
};

Related

Draw two shapes on top of each other in geometry shader?

With this small program I want to achieve:
Publish a point
Transform this point with vertex shader
Create a square and a triangle with geometry shader
Fill both the triangle and the square with fragment shader
Unfortunately, I cannot manage to superpose both shapes. I see either only the triangle or only the square. I tried to play with z but it doesn't change anything.
void main(void) {
finalColour = vec4(1.0, 0.5, 0.5, 1.0);
square(1.0, 0.0);
finalColour = vec4(0.0, 1.0, 1.0, 0.0);
triangle(vec3(0.0, 0.0, 0.0), angle[0], 1.0);
EndPrimitive();
}
void main(void) {
// finalColour = vec4(1.0, 0.5, 0.5, 1.0);
// square(1.0, 0.0);
finalColour = vec4(0.0, 1.0, 1.0, 0.0);
triangle(vec3(0.0, 0.0, 0.0), angle[0], 1.0);
EndPrimitive();
}
Main
#include <SFML/Graphics.hpp>
#include <GL/glew.h>
#include <vector>
#define WIDTH 800
int main() {
sf::RenderWindow window(sf::VideoMode(WIDTH, WIDTH), "Test");
sf::Shader shader;
shader.loadFromFile("shader.vert", "shader.geom", "shader.frag");
sf::Transform matrix = sf::Transform::Identity;
matrix.scale(1.0 / WIDTH, 1.0 / WIDTH);
sf::Glsl::Mat4 projectionViewMatrix = matrix;
shader.setUniform("projectionViewMatrix", projectionViewMatrix);
std::vector<GLfloat> vertices;
vertices.push_back(0.0); vertices.push_back(0.0); vertices.push_back(0.0);
while (window.isOpen()) {
sf::Event currEvent;
while (window.pollEvent(currEvent)) {
switch (currEvent.type) {
case(sf::Event::Closed):
window.close(); break;
}
}
window.clear(sf::Color::Black);
glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glVertexPointer(3, GL_FLOAT, 0, vertices.data());
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_POINTS, 0, vertices.size() / 3);
glDisableClientState(GL_VERTEX_ARRAY);
sf::Shader::bind(&shader);
window.display();
}
}
Vertex
#version 150
in vec3 position;
out float angle;
uniform mat4 projectionViewMatrix;
void main(void){
gl_Position = projectionViewMatrix * vec4(position.xy, 0.0 ,1.0);
angle = position.z;
}
Geometry
#version 150
layout (points) in;
layout (triangle_strip, max_vertices = 6) out;
in float angle[];
out vec4 finalColour;
uniform mat4 projectionViewMatrix;
void createVertex(vec3 offset) {
vec4 actualOffset = vec4(offset, 1.0);
vec4 worldPosition = gl_in[0].gl_Position + actualOffset;
gl_Position = worldPosition;
EmitVertex();
}
void createAngularVertex(vec3 offset, float angle, float radius) {
vec4 actualOffset = vec4(offset, 1.0);
vec4 worldPosition = gl_in[0].gl_Position + actualOffset;
gl_Position = worldPosition;
gl_Position.x += cos(angle) * radius;
gl_Position.y += sin(angle) * radius;
EmitVertex();
}
void square(float size, float z) {
createVertex(vec3(-size, -size, z));
createVertex(vec3(size, -size, z));
createVertex(vec3(-size, size, z));
createVertex(vec3(size, size, z));
createVertex(vec3(size, -size, z));
createVertex(vec3(-size, size, z));
EndPrimitive();
}
void triangle(vec3 offset, float angle, float radius) {
float pi = 3.1415;
float angleOffset = 0.5;
createAngularVertex(offset, angle, radius);
createAngularVertex(offset, angle + pi + angleOffset, radius);
createAngularVertex(offset, angle + pi - angleOffset, radius);
EndPrimitive();
}
void main(void) {
finalColour = vec4(1.0, 0.5, 0.5, 1.0);
square(1.0, 0.0);
finalColour = vec4(0.0, 1.0, 1.0, 0.0);
triangle(vec3(0.0, 0.0, 0.0), angle[0], 0.1);
EndPrimitive();
}
Fragment
#version 150
in vec4 finalColour;
out vec4 out_Colour;
void main(void){
out_Colour = vec4(finalColour.rgb, 1.0);
}
The geometry shader creates 2 primitives, one with 6 vertices and one with 3 vertices, requiring a total of 9 vertices:
layout (triangle_strip, max_vertices = 6) out;
layout (triangle_strip, max_vertices = 9) out;

The Geometry Shader is duplicating Shapes (in Processing)

I'm trying to generate a simple shape with a Geometry Shader, but the shape is rendering twice and I don't know why.
First we have a really simple Vertex Shader
#version 150
in vec4 position;
void main() {
gl_Position = position;
}
Then there's a Geometry Shader thats generating a simple triangle.
#version 150
layout (triangles) in;
layout (triangle_strip, max_vertices = 5) out;
out FragData {
vec4 color;
} FragOut;
void main(){
//RED TOP LEFT
FragOut.color = vec4(1.0, 0.0, 0.0, 1.0);
gl_Position = gl_in[0].gl_Position + vec4( -1.0, 0.0, 0.0, 0.0);
EmitVertex();
//BLUE BOTTOM LEFT
FragOut.color = vec4(0., 0., 1., 1.);
gl_Position = gl_in[0].gl_Position + vec4( -1.0, -1.0, 0.0, 0.0);
EmitVertex();
//GREEN BOTTOM RIGHT
FragOut.color = vec4(0.0, 1.0, 0.0, 1.0);
gl_Position = gl_in[0].gl_Position + vec4( 1.0, -1.0, 0.0, 0.0);
EmitVertex();
EndPrimitive();
}
And finally a simple Fragment Shader
#version 150
in FragData {
vec4 color;
} FragIn;
out vec4 fragColor;
void main() {
fragColor = FragIn.color;
}
The result should be a triangle, but TWO triangles are being rendered:
Here's the result
The Geometry Shader is executed once for each primitive. A rect() consists of 2 triangles, so the geometry shader is executed twice and generates 2 triangle_strip primitives.
Draw a single POINTS primitive instead of the rectangle:
beginShape(POINTS);
vertex(x, y);
endShape();
Note that you need to change the Primitive input specification:
layout (triangles) in;
layout (points) in;

OpenGL camera movement program vertex shader issue

So, I'm a beginner learning graphics programmer. I'm working on a program for camera movement. I think there's something wrong with the vertex shader. The program runs with no errors but the screen is completely blank. Here is the vertex shader I'm using:
#version 330
in vec4 vPosition;
out vec4 vColor;
uniform mat4 model_view;
uniform mat4 projection;
void main()
{
vec4 pos = projection * model_view * vPosition / vPosition.w;
gl_Position = pos;
vColor = vPosition;
}
If I switch the shader back to basic version:
#version 330
in vec4 vPosition;
out vec4 vColor;
void
main()
{
gl_Position = vPosition;
vColor = vPosition;
}
The program runs and renders a triangle successfully. So, I'm pretty sure the error is with the shader.
The shader is called in the initialize function:
void initialize(void)
{
glClearColor(1.0, 1.0, 1.0, 1.0); // white background
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), points, GL_STATIC_DRAW);
// Load shaders and use the resulting shader program
GLuint program = InitShader("res/shaders/vshader21.glsl", "res/shaders/fshader21.glsl");
model_view = glGetUniformLocation(program, "model_view");
projection = glGetUniformLocation(program, "projection");
glUseProgram(program);
// Initialize the vertex position attribute from the vertex shader
GLuint loc = glGetAttribLocation(program, "vPosition");
glEnableVertexAttribArray(loc);
glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
}
the 'points' in glBufferData is as follows:
const int WIDTH = 500, HEIGHT = 500;
/* Positions */
vec4 points[] = {
vec4(0.5,0.5, 1, 1),
vec4(-0.5,0.5, 1, 1),
vec4(0.5,-0.5, 1, 1) ,
vec4(-0.5,-0.5, 1, 1)
};
model_view and projection are of GLuint type in main application and global.
I set the uniform variables (position, model_view) in the display functions.
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT); // clear the window
glPointSize(20.0);
// Projection transformation parameters
GLfloat left = -1.0, right = 1.0;
GLfloat bottom = -1.0, top = 1.0;
GLfloat zNear = 0, zFar = 3.0;
mat4 p = Ortho(left, right, bottom, top, zNear, zFar);
glUniformMatrix4fv(projection, 1, GL_TRUE, p);
vec4 eye(0.0, 0.0, -1.0, 1.0);
vec4 at(0.0, 0.0, 0.0, 1.0);
vec4 up(0.0, 1.0, 0.0, 0.0);
mat4 mv = LookAt(eye, at, up);
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
glDrawArrays(GL_TRIANGLES, 0, 3); // draw the points
glFlush();
}
What could possibly be going wrong?
The explicit division by the .w component is superfluous.
vec4 pos = projection * model_view * vPosition / vPosition.w;
vec4 pos = projection * model_view * vPosition;
Note, the Perspective divide is automatically performed after clipping.
Since the vector is multiplied to the uniforms form the right, you do not have to transpose the matrices:
glUniformMatrix4fv(projection, 1, GL_TRUE, p);
glUniformMatrix4fv(projection, 1, GL_FALSE, p);
glUniformMatrix4fv(model_view, 1, GL_TRUE, mv);
glUniformMatrix4fv(model_view, 1, GL_FALSE, mv);
See GLSL Programming/Vector and Matrix Operations

Geometry shader and MVP matrices issues

I'm working with openGL's Geometry Shader, and doing some tests to get the hang of it before I move on to more complex tasks. I wrote some code to transform inputted GL_POINTS into GL_TRIANGLE_STRIPs, and I apply the MVP matrix transformation in the Geometry Shader. While rendering without the MVP matrix produces the correct output, rendering with it produces nothing. Here is the code (hopefully minimal enough):
int main(){
// Create context and window
sf::Context context;
sf::Window window(sf::VideoMode(800, 600), "Voxel Engine");
window.setVerticalSyncEnabled(true);
// Initialize glew
glewExperimental = true;
GLenum err = glewInit();
if (err != GLEW_OK){
std::cout << "glewIniti failed, aborting...\n";
}
// Create VAO
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LESS);
// Vector for verts
std::vector<glm::vec3> vertices;
// Insert a few vertices
for (int i = -5; i < 5; i++){
vertices.push_back(glm::vec3(i*.3, 0.0, 0.0));
}
// View matrix vectors
glm::vec3 eye = glm::vec3(0.0f, 5.0f, 5.0f);
glm::vec3 at = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
// Create VBO for vertices
GLuint vertexbuffer;
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);
// Create MVP matrices
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
glm::mat4 View = glm::lookAt(eye, at, up);
glm::mat4 Model = glm::mat4(1.0f);
// Load the shaders
GLuint programID = LoadShaders("VertexShader.glsl", "GeometryShader.glsl", "FragmentShader.glsl");
// Get uniform locations
GLuint M = glGetUniformLocation(programID, "M");
GLuint V = glGetUniformLocation(programID, "V");
GLuint P = glGetUniformLocation(programID, "P");
// Main loop
bool running = true;
sf::Event event;
while (running){
while (window.pollEvent(event)){
switch (event.type){
case sf::Event::Closed:
window.close();
return 0;
}
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(programID);
glUniformMatrix4fv(M, 1, GL_FALSE, &Model[0][0]);
glUniformMatrix4fv(V, 1, GL_FALSE, &View[0][0]);
glUniformMatrix4fv(P, 1, GL_FALSE, &Projection[0][0]);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glDrawArrays(GL_POINTS, 0, 10);
glDisableVertexAttribArray(0);
window.display();
}
return 0;
}
Vertex Shader:
#version 430 core
layout(location = 0) in vec3 position;
void main(){
gl_Position = vec4(position, 1);
}
Geometry Shader:
#version 430 core
layout (points) in;
uniform mat4 M, V, P;
layout (triangle_strip) out;
layout (max_vertices = 14) out;
void main(void){
// create a vertex for each point on the cube
vec4 v1 = M*V*P*(gl_in[0].gl_Position + vec4(.1, -.1, -.1, 0.0));
vec4 v2 = M*V*P*(gl_in[0].gl_Position + vec4(-.1, -.1, -.1, 0.0));
vec4 v3 = M*V*P*(gl_in[0].gl_Position + vec4(.1, .1, -.1, 0.0));
vec4 v4 = M*V*P*(gl_in[0].gl_Position + vec4(-.1, .1, -.1, 0.0));
vec4 v5 = M*V*P*(gl_in[0].gl_Position + vec4(.1, -.1, .1, 0.0));
vec4 v6 = M*V*P*(gl_in[0].gl_Position + vec4(-.1, -.1, .1, 0.0));
vec4 v7 = M*V*P*(gl_in[0].gl_Position + vec4(-.1, .1, .1, 0.0));
vec4 v8 = M*V*P*(gl_in[0].gl_Position + vec4(.1, .1, .1, 0.0));
gl_Position = v4;
EmitVertex();
gl_Position = v3;
EmitVertex();
gl_Position = v7;
EmitVertex();
gl_Position = v8;
EmitVertex();
gl_Position = v5;
EmitVertex();
gl_Position = v3;
EmitVertex();
gl_Position = v1;
EmitVertex();
gl_Position = v4;
EmitVertex();
gl_Position = v2;
EmitVertex();
gl_Position = v7;
EmitVertex();
gl_Position = v6;
EmitVertex();
gl_Position = v5;
EmitVertex();
gl_Position = v2;
EmitVertex();
gl_Position = v1;
EmitVertex();
EndPrimitive();
}
Fragment Shader:
#version 430 core
out vec4 color;
void main(){
color = vec4(0, 1, 0, 1);
}
I can provide my LoadShaders function if necessary, but I don't think the issue lies there.
So, performance aside, is there anything I'm doing which is blatantly incorrect?

OpenGL GL_INVALID_OPERATION at glDrawArrays when using tesselation shaders

I am following the OpenGL SuperBible 6th Edition and I have come upon a peculiar problem.
I have the following code rendering:
const GLfloat color[] = { 0.0f, 0.2f, 0.0f, 1.0f };
//crtime += 0.01;
glClearBufferfv(GL_COLOR, 0, color);
checkError();
glUseProgram(program);
checkError();
GLfloat attrib[] = { (float)sin(crtime) * 0.5f, (float)cos(crtime) * 0.6f, 0.0f, 0.0f };
glVertexAttrib4fv(0, attrib);
checkError();
glDrawArrays(GL_TRIANGLES, 0, 3);
checkError();
checkError() is a simple function that checks if there's any OpenGL error and prints the gluErrorString for it if there is.
My OpenGL program consists of the following shaders:
vertex.glsl
#version 430 core
layout (location = 0) in vec4 offset;
void main(void) {
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));
gl_Position = vertices[gl_VertexID] + offset;
}
tessctrlshader.glsl
#version 430 core
layout (vertices = 3) out;
void main(void) {
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = 5.0;
gl_TessLevelOuter[0] = 5.0;
gl_TessLevelOuter[1] = 5.0;
gl_TessLevelOuter[2] = 5.0;
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
tessevalshader.glsl
#version 430 core
layout (triangles) in;
void main(void) {
gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) + (gl_TessCoord.y * gl_in[1].gl_Position) + (gl_TessCoord.z * gl_in[2].gl_Position);
}
fragment.glsl
#version 430 core
out vec4 color;
void main(void) {
color = vec4(0.0, 0.8, 1.0, 1.0);
}
Here's the initialization code (LCAShader() loads from a file and prints compilation errors if any)
program = glCreateProgram();
LCAShader("vertex.glsl", program, GL_VERTEX_SHADER);
LCAShader("tessctrlshader.glsl", program, GL_TESS_CONTROL_SHADER);
LCAShader("tessevalshader.glsl", program, GL_TESS_EVALUATION_SHADER);
LCAShader("fragment.glsl", program, GL_FRAGMENT_SHADER);
glLinkProgram(program);
glGenVertexArrays(1, &vertex_array_object);
glBindVertexArray(vertex_array_object);
Every time glDrawArrays is hit, OpenGL throws an GL_INVALID_OPERATION error. However, if I remove both of the tesselation shaders, this does not happen.
I know it's an old thread but there is still no answer.
In code form book author calls glDrawArrays with GL_TRIANGLES parameter.
What you have to do is call glDrawArray(GL_PATCHES,0,3); in your render function.