使用LWJGL绘制像素图像

时间:2014-01-13 00:14:50

标签: opengl lwjgl pixel bytebuffer

我正在尝试使用java的LWJGL编写一个简单的程序。当程序运行时,我想在开头和任何时候按“' 1”时给我一个红色屏幕。如果我按下' 2'它假设给我一个黑色到白色的渐变屏幕。程序运行但是当我按下' 2'它给了我这个错误

线程中的异常" main" java.lang.IllegalArgumentException:剩余缓冲区元素的数量为0,必须至少为3686400.因为最多可以返回3686400个元素,所以无论实际返回的元素数是多少,都需要一个至少包含3686400个元素的缓冲区

at org.lwjgl.BufferChecks.throwBufferSizeException(BufferChecks.java:162)
at org.lwjgl.BufferChecks.checkBufferSize(BufferChecks.java:189)
at org.lwjgl.BufferChecks.checkBuffer(BufferChecks.java:230)
at org.lwjgl.opengl.GL11.glDrawPixels(GL11.java:1059)
at LWJGL.Lab1.render(Lab1.java:68)
at LWJGL.Game.gameLoop(Game.java:84)
at LWJGL.Game.<init>(Game.java:25)
at LWJGL.Lab1.<init>(Lab1.java:11)
at LWJGL.Lab1.main(Lab1.java:93)

我不确定ByteBuffer做错了做什么。这是我的代码。

package LWJGL;
import java.nio.ByteBuffer;

import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;

import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.util.*;

public class Lab1 extends Game
{
    private ByteBuffer raster;
    private int drawmode = 1;
    private int x,y;

    public void init()
    {
        raster= ByteBuffer.allocate(640*480*3);
        raster.asFloatBuffer();

        Display.setTitle("Tutorial 1: A simple moving rectangle");

        // Setup OpenGL
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        glMatrixMode(GL_MODELVIEW);
        glOrtho(0, 800, 600, 0, 1, -1);
        glViewport(0, 0, Display.getWidth(), Display.getHeight());

        //initialize the raster
        for(int i =0; i< raster.capacity(); i++){
            raster.put((byte) (((float)i)/(640*480*3)));
        }
    }

    public void update(long elapsedTime)
    {
        if (Keyboard.isKeyDown(Keyboard.KEY_1))
            drawmode = 1;

        if (Keyboard.isKeyDown(Keyboard.KEY_2))
            drawmode =2;

    }

    public void render()
    {
        // Render to the screen here
        glClearColor(1,0,0,1);  // Set the clear color
        // Clear the screen to the clear color (i.e. if the clear color
        // is red, the screen turns red);
        glClear(GL_COLOR_BUFFER_BIT);

        if (drawmode == 2) {
            // Save the old state so that you can set it back after you draw
            //GLint oldmatrixmode;
            boolean depthWasEnabled = glIsEnabled(GL_DEPTH_TEST);
            glDisable(GL_DEPTH_TEST);
            //glGetIntegerv(GL_MATRIX_MODE,oldmatrixmode);
            glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
            glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity();

            // Draw the array of pixels (This is where you draw the values
            // you have stored in the array 'raster')
            glRasterPos2f(-1,-1);
            GL11.glDrawPixels(640,480,GL_RGB,GL_FLOAT,raster);

            //Set the state back to what it was
            glPopMatrix();
            glMatrixMode(GL_MODELVIEW); glPopMatrix();
            //glMatrixMode(oldmatrixmode);
            if (depthWasEnabled)
              glEnable(GL_DEPTH_TEST);
        }
        glFlush();
    }

    public void resized()
    {
        // We reset the viewport here.
        glViewport(0, 0, Display.getWidth(), Display.getHeight());

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
    }

    public static void main(String[] args)
    {
        new Lab1();
    }
}

抽象类游戏不是问题。

1 个答案:

答案 0 :(得分:2)

这里有很多问题:

  1. asFloatBuffer (...)本身什么都不做。它返回另一个缓冲区,它引用与原始缓冲区相同的数据,但使用不同的表示形式。如果您不使用返回值,则没有理由调用它。

  2. 您的ByteBuffer的大小应该是存储640 * 480 * 3浮点组件的1/4。

    • GLfloat在OpenGL中必须是32位 - &gt; 4字节。

  3. ByteBuffer.put (...)会增加缓冲区的“当前”位置。这是LWJGL在将数据写入缓冲区时使用的位置。

    • 如果您没有flip缓冲区,那么您的开始位置就是缓冲区的结尾。 LWJGL会立即溢出你的缓冲区。

  4. 以下是您问题的一种可能解决方案,不需要调用raster.flip (...)(因为rasterAsFloats将其位置与raster分开存储):

    public void init()
    {
        raster                     = ByteBuffer.allocate  (640*480*4*3);
        FloatBuffer rasterAsFloats = raster.asFloatBuffer ();
    
        Display.setTitle("Tutorial 1: A simple moving rectangle");
    
        // Setup OpenGL
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
    
        glMatrixMode(GL_MODELVIEW);
        glOrtho(0, 800, 600, 0, 1, -1);
        glViewport(0, 0, Display.getWidth(), Display.getHeight());
    
        //initialize the raster
        for(int i =0; i< rasterAsFloats.capacity(); i++){
            rasterAsFloats.put ((((float)i)/(640*480*3)));
        }
    }
    

    更新

    我从未说过代码实际上会产生你想要的渐变。只是它会解决你的崩溃问题。以下是可能生成渐变的一些代码,它应该足以让您至少开始:

    for (int i = 0; i < rasterAsFloats.capacity (); i+=3) {
      float luminance = ((float)(i/(640 * 3))/480.0f);
      rasterAsFloats.put (luminance); // R
      rasterAsFloats.put (luminance); // G
      rasterAsFloats.put (luminance); // B
    }