Java / LWJGL - 无法禁用颜色钳制

时间:2014-02-24 20:34:08

标签: java lwjgl

以下解决方案

我正在尝试禁用颜色的夹紧,但它不起作用。有相同的OpenGL调用,例如可用的c ++程序。要禁用钳位,请使用以下代码:

GL30.glClampColor(GL30.GL_CLAMP_READ_COLOR, GL11.GL_FALSE);
GL30.glClampColor(GL30.GL_CLAMP_VERTEX_COLOR, GL11.GL_FALSE);
GL30.glClampColor(GL30.GL_CLAMP_FRAGMENT_COLOR, GL11.GL_FALSE);

为了更好地理解下面的完整代码以及测试类。如您所见,如果值低于零,则在交换中进行测试。我认为缓冲区是浮点缓冲区,也禁用了钳位。所以我不知道为什么它不起作用。有什么建议吗?

Canvas.java:

package render;

import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.imageio.ImageIO;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.Pbuffer;
import org.lwjgl.opengl.PixelFormat;
import org.lwjgl.util.glu.GLU;

public class Canvas {
    private final int m_width;
    private final int m_height;

    private Pbuffer m_buffer;
    private final FloatBuffer m_readBuffer;
    private final float[] m_data;
    private final FloatBuffer m_dataBuffer;

    public Canvas(final int width, final int height) {
        this.m_width = width;
        this.m_height = height;

        this.m_data = new float[this.m_width * this.m_height * 4];

        this.m_dataBuffer = FloatBuffer.wrap(this.m_data);
        this.m_readBuffer = BufferUtils.createFloatBuffer(this.m_data.length);
    }

    public void disable() {
        GL11.glPopClientAttrib();
        GL11.glPopAttrib();
    }

    public void disable2D() {
        GL11.glPopAttrib();
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPopMatrix();
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPopMatrix();
    }

    public void enable() {
        GL11.glPushClientAttrib(GL11.GL_CLIENT_VERTEX_ARRAY_BIT);
        GL11.glPushAttrib(GL11.GL_ALL_ATTRIB_BITS);

        GL30.glClampColor(GL30.GL_CLAMP_READ_COLOR, GL11.GL_FALSE);
        GL30.glClampColor(GL30.GL_CLAMP_VERTEX_COLOR, GL11.GL_FALSE);
        GL30.glClampColor(GL30.GL_CLAMP_FRAGMENT_COLOR, GL11.GL_FALSE);
    }

    public void enable2D(final int x, final int y, final int width,
            final int height) {
        GL11.glViewport(0, 0, this.m_width, this.m_height);

        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();

        GLU.gluOrtho2D(0, this.m_width, 0, this.m_height);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
        GL11.glPushMatrix();
        GL11.glLoadIdentity();

        GL11.glPushAttrib(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_LIGHTING_BIT);
        GL11.glDisable(GL11.GL_DEPTH_TEST);
        GL11.glDisable(GL11.GL_LIGHTING);
    }



    public void init() {
        try {
            if ((Pbuffer.getCapabilities() & Pbuffer.PBUFFER_SUPPORTED) == 0) {
                System.out.println("Canvas:: No PBuffer support!");
                System.exit(-1);
            }
            final PixelFormat pf = new PixelFormat();
            pf.withBitsPerPixel(32);
            pf.withFloatingPoint(true);
            this.m_buffer = new Pbuffer(this.m_width, this.m_height, pf, null);
            this.m_buffer.makeCurrent();
        } catch (final LWJGLException e) {
            System.err.println("Canvas:: Cannot create buffer!");
            e.printStackTrace();
            System.exit(-1);
        }

        if (this.m_buffer.isBufferLost()) {
            this.m_buffer.destroy();
            System.err.println("Canvas:: Buffer was lost!");
            System.exit(-1);
        }

        System.out.printf("Canvas:: Created canvas (%d %d)\n", this.m_width,
                this.m_height);
    }

    public void swap() {
        synchronized (this.m_dataBuffer) {
            GL11.glReadPixels(0, 0, this.m_width, this.m_height, GL11.GL_RGBA,
                    GL11.GL_FLOAT, this.m_readBuffer);
            while (this.m_readBuffer.remaining() > 0) {
                final float t = this.m_readBuffer.get();
                if (t < 0) {
                    System.out.println(t);
                }
                this.m_dataBuffer.put(t);
            }
            this.m_dataBuffer.rewind();
            this.m_readBuffer.rewind();
        }
    }
}

CanvasTest.java:

package OpenGLTests;

import org.lwjgl.opengl.GL11;

import render.Canvas;

public class CanvasTest {

    public static void main(final String[] args) {
        final Canvas canvas = new Canvas(100, 100);
        canvas.init();
        canvas.enable2D(0, 0, 100, 100);
        canvas.enable();

        GL11.glClearColor(-1, -1, -1, 1);

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        GL11.glColor4f(-1, -1, 1, 1);

        GL11.glBegin(GL11.GL_TRIANGLES);
        GL11.glVertex2f(0.f, 0.f);
        GL11.glVertex2f(100.f, 0.f);
        GL11.glVertex2f(50.f, 100.f);
        GL11.glEnd();

        canvas.swap();
        canvas.disable();
        canvas.disable2D();
        System.out.println("end");
    }
}


解决方案

现在我通过使用FBO修复了问题。我不知道FBO和PBO(Pbuffer)之间的区别。但是公益组织显然已经过时且过时,并且不支持超出范围的价值观。因此,您可以在下面的init()方法中查看fbo的初始化代码。使用时不要忘记绑定FBO。

    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, this.m_fbo);

    GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.m_color);
    GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL30.GL_RGBA32F, this.m_width,
            this.m_height, 0, GL11.GL_RGBA, GL11.GL_FLOAT,
            (FloatBuffer) null);

    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER,
            GL11.GL_NEAREST);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER,
            GL11.GL_NEAREST);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S,
            GL11.GL_CLAMP);
    GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T,
            GL11.GL_CLAMP);

    GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER,
            GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, this.m_color, 0);

    GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);

1 个答案:

答案 0 :(得分:0)

尝试使用:

glClampColorARB(GL_CLAMP_READ_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, GL_FALSE);
glClampColorARB(GL_CLAMP_FRAGMENT_COLOR_ARB, GL_FALSE);

我也遇到了lwjgl / unclamped颜色/浮点帧缓冲区的问题,但至少 使用glColor3f(2.0F,1.0F,1.0F)或类似的这似乎工作(没有帧缓冲区 但是,据我所知,实际上并没有浮点帧缓冲,所以这段代码将执行颜色乘法,然后将其钳制到[0F,1F]。这是理想的,因为其他任何东西都是不可显示的,但是如果你最终创建了一个松开的浮动帧缓冲区,那么你需要使用GL_RGBA16F作为格式,GL_FLOAT作为数据类型。我对这个浮点有点缺乏了解 FBO的东西(正如我自己没有想到的那样)但是这对我来说已经很有用了。我知道有些人只需要将顶点颜色设置为false,但我正在使用所有三个调用以确保它有效。顺便说一句,对于lwjgl,这些可以在org.lwjgl.opengl.ARBColorBufferFloat中找到。

GL_FIXED_ONLY_ARB可用于代替GL_FALSE。只要确保你渲染的缓冲区是浮点数,因为只有当你的缓冲区是浮点数时,fixed-only才会松开 - 整数(准确无符号字节)是默认值。

然而,再一次重申,你将无法通过读取主显示缓冲区实际找到边界外的颜色结果 - 它将被钳制,但是你将能够看到结果。正如我在我的Mac上尝试使用那些GL30功能一样,它给了我“不支持”的错误,ARB对我有用 - 但不适用于帧缓冲器。我不明白为什么,但为了你的目的,我认为这将有效。

如果有人知道我犯了大错,请纠正我。

编辑:我对帧缓冲区的问题仅仅是由于我自己的愚蠢。 HDR浮点帧缓冲区可以像这样附加HDR纹理:

glTexImage2D(GL_TEXTURE_2D, 0, hdrEnabled ? hdrFormat : GL_RGBA8, width, height, 0, GL_RGB, hdrEnabled ? hdrDataType : GL_UNSIGNED_BYTE, (java.nio.ByteBuffer) null);

我的代码中有一个小片段,hdrFormat是一个设置为GL_RGBA16F的int,而hdrDataType设置为GL_HALF_FLOAT。