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;
Related
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;
I'm doing my first steps with OpenGL and currently fail to send some transformations to my vertex shader. When I use following shader program, everything works fine and I can see my object (a simple triangle):
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0);
}
In next step I changed the shader program to accept transformations from outside:
layout (location = 0) in vec3 aPos;
uniform mat4 inputTransform;
void main()
{
gl_Position = inputTransform * vec4(aPos, 1.0);
}
...and my main loop to send transformation data to the shader:
unsigned int transformLoc = glGetUniformLocation(shaderProgram,"inputTransform");
glUseProgram(shaderProgram);
GLfloat trans[4] = {1.0, 0.0, 0.0, 1.0};
glUniformMatrix4fv(transformLoc, 1, GL_FALSE,trans);
Now my triangle disapperas as some very invalid transformation would have been applied. Value in "shaderProgram" is correct, it works properly with a prior call to the fragment shader. I also do not get any compilation errors for the shader programs.
So any idea what could be wrong here?
The uniform mat4 inputTransform is a 4*4 matrix and not a vector with 4 components.
See Data Type (GLSL) - Matrices
You have to initialize it with an array of 16 floats, e.g. by an Identity matrix:
GLfloat trans[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
glUniformMatrix4fv(transformLoc, 1, GL_FALSE, trans);
The matrix contains the translation, orientation (and scale). In GLSL a mat4 can be initialized:
mat4 m44 = mat4(
vec4( Xx, Xy, Xz, 0.0),
vec4( Yx, Xy, Yz, 0.0),
vec4( Zx Zy Zz, 0.0),
vec4( Tx, Ty, Tz, 1.0) );
This means, if you want to init the matrix with an translation vector, then you can do it manually initializing the translation component of the matrix:
Glfloat Tx = 1.0;
Glfloat Ty = 0.0;
Glfloat Tz = 0.0;
GLfloat trans[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
Tx, Ty, Tz, 1.0
};
In C++ I recommend to use the GLM library for matrix and vector operations, which are related to OpenGL and GLSL.
I try to turn around my gui. I have projection:
glm::mat4 my_projection = glm::mat4( 2.0/static_cast<float>(m_window->getSize().x), 0.0, 0.0, -1.0,
0.0, 2.0/static_cast<float>(m_window->getSize().y), 0.0, -1.0,
0.0, 0.0, -1.0, 0.0,
0.0, 0.0, 0.0, 1.0);
And shader:
#version 330 core
in vec3 pos;
in vec2 UV;
in vec4 col;
uniform vec2 translation;
uniform mat4 my_projection;
out vec2 vecUV;
out vec4 vecColor;
void main()
{
vec3 tran_pos = vec3(pos + vec3(translation, 0.0f));
gl_Position = vec4(tran_pos, 1.0f) * my_projection;
vecUV = UV;
vecColor = col;
}
And I don't know how to turn around, when I change
m_window->getSize().x
to
-m_window->getSize().x
and
m_window->getSize().y
to
-m_window->getSize().y
everything disapear. How I can turn around this?
EDIT: (SOLUTION)
glm::mat4 my_projection = glm::ortho(0.0f, (float)m_window->getSize().x, (float)m_window->getSize().y, 0.0f);
// Shader:
#version 330 core
in vec3 pos;
in vec2 UV;
in vec4 col;
uniform vec2 translation;
uniform mat4 my_projection;
out vec2 vecUV;
out vec4 vecColor;
void main()
{
vec3 tran_pos = vec3(pos + vec3(translation, 0.0f));
gl_Position = my_projection * vec4(tran_pos, 1.0f);
vecUV = UV;
vecColor = col;
}
Just use glm function to matrix projection and multiply projection by position.
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;
};
I am trying to generate a cube from 6 points (each point representing a side, then 2 extra values to say if its rotated to face on the x, or y axis, z axis doesn't need one because its like that by default). Problem comes in when I try to multiply the gl_Position value by a mat4 rotation matrix to make the sides of the cube rotated properly. It doesn't even glitch out, it just doesn't display the faces at all (it does when I dont have the matrices multiplying the values).
Heres my geometry shader:
layout(points) in;
layout(triangle_strip, max_vertices = 4) out;
in vec3 gFacePos[];
out vec2 texCoord;
mat4 xtrans = mat4( //rotate on the x axis
1.0, 0.0, 0.0, 0.0,
0.0, 0.0, -1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 ytrans = mat4( //rotate on y
0.0, 0.0, 1.0, 0.0,
0.0, 1.0, 0.0, 0.0,
-1.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 1.0
);
mat4 rtrans = (gFacePos[0].x * xtrans) + (gFacePos[0].y * ytrans); //figure out what the current point wants to rotate on
void main() { //this whole thing makes a square at the requested point
gl_Position = gl_in[0].gl_Position + vec4(-0.5, 0.5, 0.0, 0.0);
gl_Position *= rtrans; //these break it
texCoord = vec2(0.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4(0.5, 0.5, 0.0, 0.0);
gl_Position *= rtrans;
texCoord = vec2(1.0, 0.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4(-0.5, -0.5, 0.0, 0.0);
gl_Position *= rtrans;
texCoord = vec2(0.0, 1.0);
EmitVertex();
gl_Position = gl_in[0].gl_Position + vec4(0.5, -0.5, 0.0, 0.0);
gl_Position *= rtrans;
texCoord = vec2(1.0, 1.0);
EmitVertex();
EndPrimitive();
}
Fragment and vertex are pretty standard (vertex has some basic camera stuff on it).