GLSL 1.50, Geometry Shader AND Object Picking

Hello everyone…

We have OpenGL 3.2 with GLSL 1.50 with geometry shader support in the core… well…

But if we use OpenGL 3.2…where is picking mechanism…?!

Who can tell me about working algorithm to organize ray + triangle intersection using geometry shader…??

simple I say… I need picking in OpenGL 3.X core…

Help me…please…!

Use the itembuffer appoach. You render a distinct color per identifiable object into a 1x1 pixel sized FBO (with a proper projection matrix and viewport set, no MSAA enabled). Then you read back the pixel. This way you determine the ID of the foremost object. If you need per-triangle picking, you should be able to use a geometry shader and gl_PrimitiveID.

I’m using a transform foodback :slight_smile: for fill a buffer with some intersection data.
Here my shader programs “ray + triangle intersection”

Vertex

#version 120

void main(void)
{
   gl_Position = gl_ModelViewMatrix * gl_Vertex;
}

Geometry

#version 120
#extension GL_EXT_gpu_shader4 : enable
#extension GL_EXT_geometry_shader4 : enable

const float EPSILON = 1e-30;

uniform vec3 rayStart;
uniform vec3 rayVector;
uniform float MeshIndex;

varying out vec3 CustomPoint;

void main(void)
{
	vec3 v1 = (gl_PositionIn[1] - gl_PositionIn[0]).xyz;
	vec3 v2 = (gl_PositionIn[2] - gl_PositionIn[0]).xyz;
	vec3 pvec = cross(rayVector, v2);
	float det = dot(v1, pvec);
	if ((det<EPSILON) && (det>-EPSILON)) return; // vector is parallel to triangle's plane
	float invDet = 1.0 / det;
    vec3 tvec = rayStart - gl_PositionIn[0].xyz;
	float u = dot(tvec, pvec)*invDet;
	if ((u<0.0) || (u>1.0)) return;
	vec3 qvec = cross(tvec, v1);
	float v = dot(rayVector, qvec)*invDet;
	if ((v<0.0) || (u+v>1.0)) return;
	float t = dot(v2, qvec)*invDet;
	if (t<=0) return;

    // intersection point
    CustomPoint = rayVector*t + rayStart;
    EmitVertex();

	// normal in this point
	CustomPoint = normalize(cross(v1, v2));
    EmitVertex();

	// The ID of rendered mesh
	CustomPoint = vec3(MeshIndex, 0.0, 0.0);
    EmitVertex();

	// trianle's vertex A
	CustomPoint = gl_PositionIn[0].xyz;
    EmitVertex();

	// trianle's vertex B
	CustomPoint = gl_PositionIn[1].xyz;
    EmitVertex();

	// trianle's vertex C
	CustomPoint = gl_PositionIn[2].xyz;
    EmitVertex();
}

The input primitive is triangle, output - Poits.

yes…I need ray-triangle intersection…
but i don’t understand what is 1 x 1 pixel rendering target…
and how use geometry shader to get nearest ray-triangle intersection (gl_PrimitiveID)…

i don’t find any suggestion of this problem in the inet…

You don’t need rasterization for ray intersect operation


// Receive buffer
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER_EXT, 0, ReceiverID);
glBeginTransformFeedback(GL_POINTS);
// disable rasterization
glEnable(GL_RASTERIZER_DISCARD_EXT);
// begin query for geometry shader outed primitive
glBeginQuery(GL_PRIMITIVES_GENERATED_EXT, QueryID);
...
Rendering
...
// read back query results
glEndQuery( GL_PRIMITIVES_GENERATED_EXT);
glGetQueryObjectuiv(QueryID, GL_QUERY_RESULT, @PointOutNumber);
// enable rasterization
glDisable(GL_RASTERIZER_DISCARD_EXT); 

Then simply sort a output buffer data for distance to view point.

I’ve never used the gl_PrimitiveIDIn, so I can only recommend to read GLSL Spec 1.50

The input variable gl_PrimitiveIDIn is available only in the geometry language and is filled with the
number of primitives processed by the geometry shader since the current set of rendering primitives was
started.
The output variable gl_PrimitiveID is available only in the geometry language and provides a single
integer that serves as a primitive identifier. This is then available to fragment shaders as the fragment
input gl_PrimitiveID, which will select the written primitive ID from the provoking vertex in the primitive
being shaded. If a fragment shader using gl_PrimitiveID is active and a geometry shader is also active,
the geometry shader must write to gl_PrimitiveID or the fragment shader input gl_PrimitiveID is
undefined.