Java-Gaming.org    
Featured games (79)
games approved by the League of Dukes
Games in Showcase (477)
Games in Android Showcase (106)
games submitted by our members
Games in WIP (533)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Possible bug wt GLSL access of GL_TEXTURE_2D on Geforce 8  (Read 1339 times)
0 Members and 1 Guest are viewing this topic.
Offline AI Guy

Senior Newbie





« Posted 2008-02-13 22:18:35 »

I believe I can demonstrate a bug with the GeForce 8800 GTX/PCI/SSE2 renderer, version 2.1.2 (ForceWare 169.25, on Vista).  I wish very much to be wrong, since then it will be within my control to fix .  Please take class below, and let me know of results of trying to reproduce on same or different hardware.

First, like the JOGL Texture class, I wish to dynamically use OpenGL 2.0 features when detected.  For textures, that means using GL_TEXTURE_2D textures, instead of GL_TEXTURE_RECTANGLE_ARB.

I am using GLSL, so doing this also requires that the source for the shader be generated on the fly.  This is not an obstacle, since I am already doing this to do things like specify sizes of arrays.

My self contained JOGL class, Texture2DProblem,  takes a boolean argument isNPO2, which sets 3 members that control which type of texture to use.  A PBuffer is created, but a framebuffer is used to all rendering / retrieving results from.  This is what the program does in init():
  • Creates a fragment shader, which returns it's X gl_TexCoord & the value from a texture read using it's coordinate.
  • Builds a texture, containing the offset from the beginning in each of it's 4 elements.
  • Associates that texture with the sampler in the shader
  • Creates a frame buffer with single attachment, mapped to above texture

The display() method, renders a 1 row quad, and displays a row of X coord & texture value.

When using GL_TEXTURE_RECTANGLE_ARB everything works as expected.  The GL_TEXTURE_2D version gets the X coord right, the texture lookup returns the first texel, or the last texel.  Is there a way this could not be a bug?

FYI, this class is meant to be as straight forward as possible.  Not included but also checked was:
  • Using older ARG version of shaders produces the same results.
  • Using a PBuffer by itself also produces the same results.

This is my output::
results of GL_TEXTURE_RECTANGLE_ARB: 
============================
uniform  sampler2DRect  texNm;
void main() {
    vec4 tCoords = floor(gl_TexCoord[0]);
    vec4 texture = texture2DRect(texNm, vec2(tCoords) );
    texture.x = tCoords.x;
    gl_FragColor = texture;
}
Frag X coord :  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0
Texture Value:  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0

results of GL_TEXTURE_2D: 
============================
uniform  sampler2D  texNm;
void main() {
    vec4 tCoords = floor(gl_TexCoord[0]);
    vec4 texture = texture2D(texNm, vec2(tCoords) );
    texture.x = tCoords.x;
    gl_FragColor = texture;
}
Frag X coord :  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0
Texture Value:  0.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0
Offline AI Guy

Senior Newbie





« Reply #1 - Posted 2008-02-13 22:19:11 »

Class:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
174  
175  
176  
177  
178  
179  
180  
181  
182  
183  
184  
185  
186  
187  
188  
189  
import java.nio.*;
import javax.media.opengl.*;
import javax.media.opengl.glu.GLU;
import com.sun.opengl.util.BufferUtil;

public class Texture2DProblem implements GLEventListener{
    public static void main(String[] argv) throws Exception{
        System.out.println("\nresults of GL_TEXTURE_RECTANGLE_ARB:  ");
        System.out.println("============================");
        Texture2DProblem card = new Texture2DProblem(false);        
        card.pBuffer.display();
        card.pBuffer.destroy();
       
        System.out.println("\nresults of GL_TEXTURE_2D:  ");
        System.out.println("============================");
        card = new Texture2DProblem(true);        
        card.pBuffer.display();
        card.pBuffer.destroy();
    }
    final int       textureTarget;
    final String    texUniform;
    final String    texFunc;
    final GLPbuffer pBuffer;

    static final int WDITH = 10; // changing this, changes the amount of screw-up
   static final int HEIGHT = 1;
   
    static final int TEX_UNIT_NO = 0; // texture units sequential, so offset
   static final int FBO_ATTACHMENT = GL.GL_COLOR_ATTACHMENT0_EXT;
   
    public Texture2DProblem(boolean isNPO2){
        if (isNPO2) {
            textureTarget = GL.GL_TEXTURE_2D;
            texUniform = " sampler2D ";
            texFunc = "texture2D";
        } else {
            textureTarget = GL.GL_TEXTURE_RECTANGLE_ARB;
            texUniform = " sampler2DRect ";
            texFunc = "texture2DRect";
        }
       
        GLCapabilities caps = new GLCapabilities();
        caps.setDoubleBuffered(false);

        // using fbo for all rendering, so get minimum sized pbuffer
       pBuffer = GLDrawableFactory.getFactory().createGLPbuffer(caps, null, 1, 1, null);        
        // not thread safe to let 'this' escape in constructor, do not do in production
       pBuffer.addGLEventListener(this);
    }
    public void init(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();
//        gl = new TraceGL(gl, System.err);
       
        int shaderId = createFragmentShader(gl,
                "uniform " + texUniform + " texNm;" +
                "\nvoid main() {" +
                "\n    vec4 tCoords = floor(gl_TexCoord[0]);" +
                "\n    vec4 texture = " + texFunc + "(texNm, vec2(tCoords) );" +
                "\n    texture.x = tCoords.x;" +
                "\n    gl_FragColor = texture;"+
                "\n}",
                true);
       
        int prgmId = createAttachLinkUseProgram(gl, new int[]{shaderId});
       
        // load identity texture, and associate with sampler & bind to texture unit
       int texId = loadTexture(gl, get4ElementIdentityBuffer(WDITH, HEIGHT) );  
        associateTexture(gl, prgmId, TEX_UNIT_NO, "texNm", texId);
       
        // create and assign FBO to above texture,  can get away with only 1 fbo,
       // since only reading the same texel as writing
        int[] fb = new int[1];
        gl.glGenFramebuffersEXT(1, fb, 0);
    gl.glBindFramebufferEXT(GL.GL_FRAMEBUFFER_EXT, fb[0]);
       gl.glFramebufferTexture2DEXT(GL.GL_FRAMEBUFFER_EXT, FBO_ATTACHMENT, textureTarget, texId, 0);
    }
    public void display(GLAutoDrawable drawable) {
        GL gl = drawable.getGL();
//        gl = new TraceGL(gl, System.err);
       
        renderQuad(gl, FBO_ATTACHMENT, WDITH, HEIGHT);
       
        // copy Attachment to a float buffer
       FloatBuffer buf = BufferUtil.newFloatBuffer(4 * WDITH * HEIGHT);        
        gl.glReadBuffer (FBO_ATTACHMENT);
        gl.glReadPixels(0, 0, WDITH, HEIGHT, GL.GL_RGBA, GL.GL_FLOAT, buf);
       
        // read thru float buffer and display results
       String coord = "Frag X coord :  ";
        String value = "Texture Value:  ";
        float[] pix = new float[4];
        for (int w = 0; w < WDITH; w++) {
            buf.get(pix);
            coord += ((w> 0) ? ", " : "") + pix[0];
            value += ((w> 0) ? ", " : "") + pix[1];
        }
        System.out.println(coord);
        System.out.println(value);
    }
    public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {}
    public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {}

    int createFragmentShader(GL gl, String source, boolean display){
        int shaderID = gl.glCreateShader(GL.GL_FRAGMENT_SHADER);

        String[] srcArray = source.split("\n");
        int count = srcArray.length;

        int[] lengths = new int[count];
        for (int i = 0; i < count; i++) {
            if (display) System.out.println(srcArray[i]);
            lengths[i] = srcArray[i].length();
        }
        gl.glShaderSource(shaderID, count, srcArray, lengths, 0);
        gl.glCompileShader(shaderID);

        return shaderID;
    }
    int createAttachLinkUseProgram(GL gl, int[] shaderIDs){
        // create the program
       int prgmID = gl.glCreateProgram();
       
        // attach each of the shaders
       for(int i = 0; i < shaderIDs.length; i++){
             gl.glAttachShader(prgmID, shaderIDs[i] );
        }
       
        //link & use the program
       gl.glLinkProgram(prgmID);
        gl.glUseProgram(prgmID);
       
        return prgmID;
   }
 
    int loadTexture(GL gl, FloatBuffer buf){        
        int[] texID = new int[1];
        // create a new texture name
       gl.glGenTextures(1, texID, 0);

        // bind the texture name to a texture target
       gl.glBindTexture(textureTarget, texID[0]);
        gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MIN_FILTER, GL.GL_NEAREST);
        gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_MAG_FILTER, GL.GL_NEAREST);
        gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
        gl.glTexParameteri(textureTarget, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);

        gl.glTexImage2D(textureTarget, 0, GL.GL_RGBA32F_ARB, WDITH, HEIGHT, 0, GL.GL_RGBA, GL.GL_FLOAT, buf);
        gl.glEnable(textureTarget);

        return texID[0];
        }
     void associateTexture(GL gl, int prgmID, int unitNo, String samplerNm, int textureID) {        
        int sampler = gl.glGetUniformLocation(prgmID, samplerNm);
        gl.glUniform1i(sampler, unitNo);

        gl.glActiveTexture(GL.GL_TEXTURE0 + unitNo);
        gl.glBindTexture(textureTarget, textureID );
    }
     FloatBuffer get4ElementIdentityBuffer(int width, int height) {
        int nTexels = width * height;
        int tVals = 4 * nTexels;
        FloatBuffer buffer = BufferUtil.newFloatBuffer(tVals);

        for (int i = 0; i < nTexels; i++)
            buffer.put(new float[] {i, i, i, i} );

        buffer.rewind();
        return buffer;
    }
     void renderQuad(GL gl, int buffer, int width, int height){
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        (new GLU()).gluOrtho2D(0, width, 0, height);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
         
        // assign buffer to render
       gl.glDrawBuffer(buffer);
       
        // ensure Texture unit 0 has the coordinates, explicitly
       gl.glBegin(GL.GL_QUADS);
        gl.glTexCoord2i(0    , 0     ); gl.glVertex2i(0    , 0     );
        gl.glTexCoord2i(width, 0     ); gl.glVertex2i(width, 0     );
        gl.glTexCoord2i(width, height); gl.glVertex2i(width, height);
        gl.glTexCoord2i(0    , height); gl.glVertex2i(0    , height);
        gl.glEnd();
    }
}

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #2 - Posted 2008-02-14 00:05:58 »

It isn't obvious what the problem is from your description. Regardless, I don't think there's any bug in JOGL here. I suspect it's either a bug in your code / shader or in the OpenGL driver. JOGL does no interposition or anything else with any of these calls.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Chris61182

Junior Member





« Reply #3 - Posted 2008-02-14 00:25:11 »

I've only a quick moment to look through your code, so I may be mistaken but I believe the issue you're seeing is in the texture coordinates. Texture rectangles use coordinates between 0 and the resolution in that dimension and don't support mirroring, wrapping, repeating. Otherwise texture coordinates need to be between 0 and 1, and values beyond that range are clamped, wrapped, repeated, or mirrored depending on the state set by glTexParameteri().

So you might want to double check that the coordinates are correct for the appropriate mode.


Actually yes, that looks to be exactly the problem. Frag X coord in the non-rectangle case should actually be 0.0, 0.1, 0.2, 0.3, ..... 1.0
Quote
This is my output::
results of GL_TEXTURE_RECTANGLE_ARB:
============================
uniform  sampler2DRect  texNm;
void main() {
    vec4 tCoords = floor(gl_TexCoord[0]);
    vec4 texture = texture2DRect(texNm, vec2(tCoords) );
    texture.x = tCoords.x;
    gl_FragColor = texture;
}
Frag X coord :  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0
Texture Value:  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0

results of GL_TEXTURE_2D:
============================
uniform  sampler2D  texNm;
void main() {
    vec4 tCoords = floor(gl_TexCoord[0]);
    vec4 texture = texture2D(texNm, vec2(tCoords) );
    texture.x = tCoords.x;
    gl_FragColor = texture;
}
Frag X coord :  0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0
Texture Value:  0.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0, 9.0
Offline AI Guy

Senior Newbie





« Reply #4 - Posted 2008-02-14 16:28:56 »

Chris,

Thanks!  I guess, I created unnecessary problems in trying to do some future proofing of my app.  I had not found any info which contrasts all of the various texture targets, in enough detail, in a way I understood, for me to spot this.   GL_TEXTURE_RECTANGLE_ARB is not even mentioned in Redbook..

I need exact texels from my texture lookups, so I'll just use GL_TEXTURE_RECTANGLE_ARB.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

pw (26 views)
2014-07-24 01:59:36

Riven (25 views)
2014-07-23 21:16:32

Riven (19 views)
2014-07-23 21:07:15

Riven (22 views)
2014-07-23 20:56:16

ctomni231 (51 views)
2014-07-18 06:55:21

Zero Volt (46 views)
2014-07-17 23:47:54

danieldean (37 views)
2014-07-17 23:41:23

MustardPeter (40 views)
2014-07-16 23:30:00

Cero (56 views)
2014-07-16 00:42:17

Riven (55 views)
2014-07-14 18:02:53
HotSpot Options
by dleskov
2014-07-08 03:59:08

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:58:24

Java and Game Development Tutorials
by SwordsMiner
2014-06-14 00:47:22

How do I start Java Game Development?
by ra4king
2014-05-17 11:13:37

HotSpot Options
by Roquen
2014-05-15 09:59:54

HotSpot Options
by Roquen
2014-05-06 15:03:10

Escape Analysis
by Roquen
2014-04-29 22:16:43

Experimental Toys
by Roquen
2014-04-28 13:24:22
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!