问题
So, I am trying to implement the picking through id. This means with every drawArray a different unique id will be set as uniform and saved in the red component on a texture.
16 bits are more than enough (65k elements), so I choose to use shorts, I know that uniform variable can be only ui, but I decided to gave it a try anyway
I also found another question, here, where the answer contains a small example with shorts
However here my code to initialize the framebuffer and two textures, one for the depth and one for the color_attachment0 with just the red component with 16
textures = new int[2];
fbo = new int[1];
gl3.glGenTextures(2, textures, 0);
gl3.glGenFramebuffers(1, fbo, 0);
/**
* Depth.
*/
gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, textures[depth]);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_DEPTH_COMPONENT32F, width, height, 0, GL3.GL_DEPTH_COMPONENT, GL3.GL_FLOAT, null);
/**
* IDs.
*/
gl3.glBindTexture(GL3.GL_TEXTURE_RECTANGLE, textures[id]);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_S, GL3.GL_CLAMP_TO_EDGE);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_WRAP_T, GL3.GL_CLAMP_TO_EDGE);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MIN_FILTER, GL3.GL_NEAREST);
gl3.glTexParameteri(GL3.GL_TEXTURE_RECTANGLE, GL3.GL_TEXTURE_MAG_FILTER, GL3.GL_NEAREST);
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16UI, width, height, 0, GL3.GL_RED, GL3.GL_UNSIGNED_SHORT, null);
/**
* FBO.
*/
gl3.glBindFramebuffer(GL3.GL_FRAMEBUFFER, fbo[0]);
gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_DEPTH_ATTACHMENT, GL3.GL_TEXTURE_RECTANGLE, textures[depth], 0);
gl3.glFramebufferTexture2D(GL3.GL_FRAMEBUFFER, GL3.GL_COLOR_ATTACHMENT0, GL3.GL_TEXTURE_RECTANGLE, textures[id], 0);
I get the following error at the id-glTexImage2D
GLDebugEvent[ id 0x502
type Error
severity High: dangerous undefined behavior
source GL API
msg GL_INVALID_OPERATION error generated. Texture type and format combination is not valid.
when 1391769197680
source 4.4 (Compat profile, arb, debug, ES2 compat, ES3 compat, FBO, hardware) - 4.4.0 - hash 0x1c19b340]
java.lang.Exception: Stack trace
at java.lang.Thread.dumpStack(Thread.java:1364)
at jogamp.opengl.GLDebugMessageHandler$StdErrGLDebugListener.messageSent(GLDebugMessageHandler.java:308)
at jogamp.opengl.GLDebugMessageHandler.sendMessage(GLDebugMessageHandler.java:293)
at jogamp.opengl.GLDebugMessageHandler.glDebugMessageARB(GLDebugMessageHandler.java:319)
at jogamp.opengl.gl4.GL4bcImpl.dispatch_glTexImage2D1(Native Method)
at jogamp.opengl.gl4.GL4bcImpl.glTexImage2D(GL4bcImpl.java:27313)
at javax.media.opengl.DebugGL4bc.glTexImage2D(DebugGL4bc.java:19874)
at ec.rendering.input.picking.EC_Picking.initRenderingTargets(EC_Picking.java:107)
For completeness, here the VS:
#version 330
layout (location = 0) in vec3 position;
uniform mat4 modelToWorldMatrix;
layout(std140) uniform GlobalMatrices {
mat4 worldToCameraMatrix;
mat4 cameraToClipMatrix;
};
void main() {
gl_Position = cameraToClipMatrix * (worldToCameraMatrix * vec4(position, 1.0));
}
modelToWorldMatrix is not yet taken in account at the moment
And here the FS:
#version 330
uniform uint id;
out vec4 outputColor;
void main() {
outputColor = vec4(id, 0, 0, 1);
}
Using shorts is feasible?
Jogl, Opengl 3.3
Edit: it looks now I solved that part with
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_SHORT, null);
but now I get an error when I try to set the short uniform value
gl3.glUniform1i(pickModel.getIdUL(), (int)mesh.getId());
Error
GLDebugEvent[ id 0x502
type Error
severity High: dangerous undefined behavior
source GL API
msg GL_INVALID_OPERATION error generated. Wrong component type or count.
when 1391779682993
source 4.4 (Compat profile, arb, debug, ES2 compat, ES3 compat, FBO, hardware) - 4.4.0 - hash 0x5ee072e3]
The uniform location seems correct since it is not -1 (1 actually)...
So how could I upload a short?
回答1:
Most of your problems are related to the fact that OpenGL isn't as gracious with conversions as you might expect it to be.
First of all for a glUniform
call the type and size of the uniform variable has to match the function exactly. Specifically, the documentation says:
GL_INVALID_OPERATION
is generated if one of the signed integer variants of this function is used to load a uniform variable of type unsigned int, uvec2, uvec3, uvec4, or an array of these.
Thus you have to use glUniform1ui
instead (mind the u!) if your id
variable is a uint
.
Other than that there's also a mismatch between your framebuffer's output format and your shader's output format. If you want to write into an integer texture, you need to write actual integers from your shader, thus change your outputColor
to
out int outputID;
or maybe
out ivec4 outputID;
if neccessary (or with a "u" if using GL_R16UI
of course).
And by the way, are you sure you need a signed integer texture (as unsigned would be much more natural for your use case)? You say that changing the glTexImage2D
call to
gl3.glTexImage2D(GL3.GL_TEXTURE_RECTANGLE, 0, GL3.GL_R16I, width, height, 0, GL3.GL_RED_INTEGER, GL3.GL_SHORT, null);
made the texture error disappear, but this may very well have been because of the use of GL_RED_INTEGER
instead of just GL_RED
and not necessarily because of the use of a signed format. So GL_R16UI
together with GL_UNSIGNED_SHORT
and GL_RED_INTEGER
(and of course a uint
or uvec4
for the output variable) would be worth a try.
Just keep in mind that the types always have to match.
来源:https://stackoverflow.com/questions/21625709/jogl-creating-only-red-channel-u16-but-getting-texture-type-and-format-combina