I am trying to build a Geometry shader that takes points as inputs and displays a textured plane for each point
Here is a one-file version of what I am working with:
main.cpp
#include "ofMain.h"
#define STRINGIFY(x) #x
class ofApp : public ofBaseApp
{
public:
ofShader shader;
ofEasyCam camera;
ofVboMesh mesh;
ofPlanePrimitive plane;
ofTexture texture;
ofFbo fbo;
void setup()
{
// ofDisableArbTex();
ofEnableAlphaBlending();
//ofEnableNormalizedTexCoords();
ofFbo::Settings settings;
settings.width = 256;
settings.height = 256;
settings.textureTarget = GL_TEXTURE_RECTANGLE_ARB; // GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE_ARB
settings.internalformat = GL_RGBA; // GL_RGBA, GL_RGBA16F_ARB, GL_RGBA32F_ARB, GL_LUMINANCE32F_ARB etc.
//settings.depthStencilInternalFormat = GL_DEPTH_STENCIL; // GL_DEPTH_COMPONENT(16/24/32)
//settings.wrapModeHorizontal = GL_REPEAT; // GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER etc.
//settings.wrapModeVertical = GL_REPEAT; // GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER etc.
//settings.minFilter = GL_REPEAT; // GL_NEAREST, GL_LINEAR etc.
//settings.maxFilter = GL_REPEAT; // GL_NEAREST, GL_LINEAR etc.
settings.numSamples=0; // number of samples for multisampling (set 0 to disable)
fbo.allocate(settings);
fbo.begin();
ofClear(0);
int step = 32;
int numRows, numCols;
numRows = numCols = fbo.getWidth() / step;
ofColor color1 = ofColor::white;
ofColor color2= ofColor::black;
ofColor lastColor = color1;
for (int y = 0; y < numRows; y++)
{
for (int x = 0; x < numCols; x++)
{
ofSetColor(lastColor);
ofDrawRectangle(x * step, y * step, step, step);
if(lastColor == color1)
{
lastColor = color2;
}else
{
lastColor = color1;
}
if (x + 1 == numCols && x % 2 != 0)
{
if(lastColor == color1)
{
lastColor = color2;
}else
{
lastColor = color1;
}
}
}
}
fbo.end();
texture = fbo.getTexture();
string shaderHeader = "#version 330\n";
string vertShaderSource = shaderHeader;
string fragShaderSource = shaderHeader;
string geomShaderSource = shaderHeader;
vertShaderSource += STRINGIFY(
// these are passed in from OF programmable renderer
uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 textureMatrix;
uniform mat4 normalMatrix;
in vec4 position;
in vec2 texcoord;
out VS_OUT {
vec4 texCoordVaryingOut;
}vs_out;
void main()
{
//enabling this will cause shader to compile but fail even though unused?
//vs_out.texCoordVaryingOut = texcoord.x;
gl_Position = position;
}
);
geomShaderSource += STRINGIFY(
layout (points) in;
layout (triangle_strip, max_vertices = 4) out;
uniform mat4 modelViewProjectionMatrix;
out vec4 outputColor;
uniform sampler2DRect geomTexture;
uniform float imgWidth;
uniform float imgHeight;
uniform vec4 globalColor;
out vec2 geomTexCoordVarying;
in VS_OUT {
vec4 texCoordVaryingOut;
} gs_in[];
void main()
{
//= gs_in[0].texCoordVaryingOut;
vec4 position = gl_in[0].gl_Position;
float size = 10.0f;
vec2 t1 = vec2(0.0f, 0.0f);
vec2 t2 = vec2(imgWidth, 0.0f);
vec2 t3 = vec2(imgWidth, imgHeight);
vec2 t4 = vec2(0.0f, imgHeight);
vec4 outputPosition;
vec4 tPos;
vec4 localPosition = vec4(-size, -size, 0.0f, 0.0f); // 1:bottom-left
outputPosition = position + localPosition;
tPos = modelViewProjectionMatrix *outputPosition;
gl_Position = tPos;
geomTexCoordVarying = t3;
outputColor = texture(geomTexture, geomTexCoordVarying)*globalColor;
EmitVertex();
localPosition =vec4( size, -size, 0.0f, 0.0f); // 2:bottom-right
outputPosition = position + localPosition;
tPos = modelViewProjectionMatrix *outputPosition;
gl_Position = tPos;
geomTexCoordVarying = t4;
outputColor = texture(geomTexture, geomTexCoordVarying)*globalColor;
EmitVertex();
localPosition =vec4(-size, size, 0.0f, 0.0f); // 3:top-left
outputPosition = position + localPosition;
tPos = modelViewProjectionMatrix *outputPosition;
gl_Position = tPos;
geomTexCoordVarying = t1;
outputColor = texture(geomTexture, geomTexCoordVarying)*globalColor;
EmitVertex();
localPosition =vec4( size, size, 0.0f, 0.0f); // 4:top-right
outputPosition = position + localPosition;
tPos = modelViewProjectionMatrix *outputPosition;
gl_Position = tPos;
geomTexCoordVarying = t2;
outputColor = texture(geomTexture, geomTexCoordVarying)*globalColor;
EmitVertex();
EndPrimitive();
}
);
//3, 4, 1, 2
fragShaderSource += STRINGIFY(
in vec4 outputColor;
out vec4 fragColor;
uniform vec4 globalColor;
uniform sampler2DRect geomTexture;
in vec2 geomTexCoordVarying;
void main (void)
{
//use the Geometry Shader outputColor
//fragColor = outputColor;
//ignore the Geometry Shader outputColor
fragColor = texture(geomTexture, geomTexCoordVarying)*globalColor;
}
);
shader.setupShaderFromSource(GL_VERTEX_SHADER, vertShaderSource);
shader.setupShaderFromSource(GL_FRAGMENT_SHADER, fragShaderSource);
shader.setupShaderFromSource(GL_GEOMETRY_SHADER, geomShaderSource);
shader.linkProgram();
plane.set(256, 256, 5, 5);
mesh = ofVboMesh(plane.getMesh());
mesh.setMode(OF_PRIMITIVE_POINTS);
}
void update()
{
}
void draw()
{
ofPushStyle();
camera.begin();
texture.bind();
shader.begin();
ofSetColor(ofColor::red, 255);
//shader.setUniformTexture("geomTexture", texture, 1);
shader.setUniform1f("imgWidth", texture.getWidth());
shader.setUniform1f("imgHeight", texture.getHeight());
mesh.drawFaces();
mesh.drawWireframe();
shader.end();
texture.unbind();
mesh.drawWireframe();
camera.end();
ofPopStyle();
texture.draw(0, 0);
}
void keyPressed (int key)
{
}
};
int main( ){
ofSetLogLevel(OF_LOG_VERBOSE);
ofGLFWWindowSettings settings;
settings.setGLVersion(4, 1);
settings.width = 1280;
settings.height = 720;
ofCreateWindow(settings);
ofRunApp(new ofApp());
}
The current output above looks like this:
I’ve tried a few things but these seem to make it worse or the texture isn’t drawn at all
-
GL_TEXTURE_2D
for the Texture ofDisableArbTex
ofEnableNormalizedTexCoords
Stranger things:
In order to pass something from the Vertex Shader to the Geometry Shader I am supposed to use an array. However if I try and do this the shader compiles but fails?
@hahakid ?