lwjgl で簡単なレンダリング エンジンを作成しようとしていますが、問題が発生しています。Immediate モードから離れて、drawArrays を使用することにしました。ただし、テクスチャをレンダリングしようとするとすぐに結果が表示されません。画像が表示されません。これが私のレンダラークラスです:
package com.nightfall.morningside;
import java.nio.*;
import com.nightfall.morningside.geometry.*;
import com.nightfall.morningside.windowingtoolkit.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
public class Renderer {
float LineWidth = 1.0f;
public void setLineWidth(float width){
LineWidth = width;
}
/*
* you can pass a com.morningside.geometry.Rectangle to this function if you don't want to use the one with floats.
*/
public void drawRectangle(Rectangle r, Colour fill){
drawRectangle(r.getX1(), r.getY1(), r.getWidth(), r.getHeight(), fill);
}
public void drawRectangle(float x1, float y1, float w, float h, Colour fill){
drawTriangle(x1, y1, x1 + w, y1 + h, x1, y1 + h, fill);
drawTriangle(x1 + w, y1, x1, y1, x1 + w, y1 + h, fill);
}
public void drawColouredRectangle(ColouredRectangle r){
drawColouredRectangle(r.getX1(), r.getY1(), r.getWidth(), r.getHeight(), r.getColour1(), r.getColour2(), r.getColour3(), r.getColour4());
}
public void drawColouredRectangle(float x1, float y1, float w, float h, Colour c1, Colour c2, Colour c3, Colour c4){
drawColouredTriangle(x1, y1, x1 + w, y1 + h, x1, y1 + h, c1, c3, c4);
drawColouredTriangle(x1 + w, y1, x1, y1, x1 + w, y1 + h, c2, c1, c3);
}
public void drawLine(Point p1, Point p2, Colour c){
drawLine(p1.getX(), p1.getY(), p2.getX(), p2.getY(), c);
}
public void drawLine(float x1, float y1, float x2, float y2, Colour c){
/*GL11.glBegin(GL11.GL_LINE_STRIP);
GL11.glLineWidth(LineWidth);
GL11.glColor4f(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
GL11.glVertex2f(x1, y1);
GL11.glVertex2f(x2, y2);
GL11.glEnd(); */
FloatBuffer vb = BufferUtils.createFloatBuffer(6);
vb.put(x1).put(y1).put(0f);
vb.put(x2).put(y2).put(0f);
vb.flip();
FloatBuffer cb = BufferUtils.createFloatBuffer(8);
cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
cb.flip();
GL11.glEnable(GL11.GL_VERTEX_ARRAY);
GL11.glEnable(GL11.GL_COLOR_ARRAY);
GL11.glColorPointer(4, 4 << 2, cb);
GL11.glVertexPointer(2, 0, vb);
GL11.glDrawArrays(GL11.GL_LINE_STRIP, 0, 2);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
}
public void drawTriangle(Triangle t, Colour c){
drawTriangle(t.getX1(), t.getY1(), t.getX2(), t.getY2(), t.getX3(), t.getY3(), c);
}
public void drawTriangle(float x1, float y1, float x2, float y2, float x3, float y3, Colour c){
//this is the way it should be done
FloatBuffer vb = BufferUtils.createFloatBuffer(9);
vb.put(x1).put(y1).put(0f);
vb.put(x2).put(y2).put(0f);
vb.put(x3).put(y3).put(0f);
vb.flip();
FloatBuffer cb = BufferUtils.createFloatBuffer(12);
cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
cb.put(c.getRed()).put(c.getBlue()).put(c.getGreen()).put(c.getAlpha());
cb.flip();
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glColorPointer(4, 4 << 2, cb);
GL11.glVertexPointer(3, 3 << 2, vb);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
}
public void drawColouredTriangle(ColouredTriangle t){
drawColouredTriangle(t.getX1(), t.getY1(), t.getX2(), t.getY2(), t.getX3(), t.getY3(), t.getColour1(), t.getColour2(), t.getColour3());
}
public void drawColouredTriangle(float x1, float y1, float x2, float y2, float x3, float y3, Colour c1, Colour c2, Colour c3){
//this is the way it should be done
FloatBuffer vb = BufferUtils.createFloatBuffer(9);
vb.put(x1).put(y1).put(0f);
vb.put(x2).put(y2).put(0f);
vb.put(x3).put(y3).put(0f);
vb.flip();
FloatBuffer cb = BufferUtils.createFloatBuffer(12);
cb.put(c1.getRed()).put(c1.getGreen()).put(c1.getBlue()).put(c1.getAlpha());
cb.put(c2.getRed()).put(c2.getGreen()).put(c2.getBlue()).put(c2.getAlpha());
cb.put(c3.getRed()).put(c3.getGreen()).put(c3.getBlue()).put(c3.getAlpha());
cb.flip();
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_COLOR_ARRAY);
GL11.glColorPointer(4, 4 << 2, cb);
GL11.glVertexPointer(3, 3 << 2, vb);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, 3);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_COLOR_ARRAY);
}
public void drawCircle(){
//GL11.glBegin(GL11.gl_);
}
public void drawTexturedRectangle(TexturedRectangle t){
//GL11.glColor4f(fill.getRed(), fill.getGreen(), fill.getBlue(), fill.getAlpha());
drawTexturedRectangle(t.getX1(), t.getY1(), t.getWidth(), t.getHeight(), t.getTexture());
}
public void drawTexturedRectangle(float x1, float y1, float w, float h, Texture t){
/*for some reason, we need to only have GL_TEXTURE_2D enabled when we're actually rendering a
texture because otherwise weird things happen */
GL11.glEnable(GL11.GL_TEXTURE_2D);
drawRectangle(x1, y1, w, h, Colour.ORANGE);
FloatBuffer vb = BufferUtils.createFloatBuffer(2*4);
FloatBuffer tex = BufferUtils.createFloatBuffer(2*4);
t.bind();
//GL11.glBindTexture(GL11.GL_TEXTURE_2D, t.id);
vb.put(new float[] {
// X Y
x1, y1, // <- First vertex
x1 + w, y1, // <- Second vertex
x1 + w, y1 + h, // <- Third vertex
x1, y1 + h // <- Fourth vertex
});
tex.put(new float[] {
// X Y
0, 0, // <- First texture coord
1, 0, // <- Second texture coord
1, 1, // <- Third texture coord
0, 1 // <- Fourth texture coord
});
tex.rewind();
vb.rewind();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, t.id);
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
GL11.glTexCoordPointer(4, 0, tex);
GL11.glVertexPointer(4, 0, vb);
GL11.glDrawArrays(GL11.GL_QUADS, 0, 4);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
}
public void drawTexture(float x1, float y1, float w, float h, Texture t){
drawTexturedRectangle(x1, y1, w, h, t);
}
public void drawString(String s, float x1, float y1, float width, float height, Colour c, Font f){
GL11.glColor4f(1f, 1f, 1f, 1f);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glPushMatrix();
f.bind();
GL11.glTranslatef(x1, y1, 0);
for (int i = 0; i < s.length(); i++){
float x = f.charAt(s.charAt(i)).getX();
GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(x, 0);
GL11.glVertex2f(i * width, 0);
GL11.glTexCoord2f(x, 1);
GL11.glVertex2f(i * width, height);
GL11.glTexCoord2f(x + 0.01f, 1);
GL11.glVertex2f(width + (i * width), height);
GL11.glTexCoord2f(x + 0.01f, 0);
GL11.glVertex2f(width + (i * width), 0);
}
GL11.glEnd();
}
GL11.glPopMatrix();
GL11.glDisable(GL11.GL_TEXTURE_2D);
}
}
一部のコードはまだ非推奨のメソッドを使用しています。これは、まだすべてをロールオーバーしていないためです。Texture クラスのコードは次のとおりです。
/*
* Sourced code from:
* https://github.com/mattdesl/lwjgl-basics/wiki/Textures
* Will adapt this soon
*/
package com.nightfall.morningside;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.ByteBuffer;
import org.lwjgl.BufferUtils;
import de.matthiasmann.twl.utils.PNGDecoder;
public class Texture {
public final int target = GL_TEXTURE_2D;
public final int id;
public final int width;
public final int height;
public static final int LINEAR = GL_LINEAR;
public static final int NEAREST = GL_NEAREST;
public static final int CLAMP = GL_CLAMP;
public static final int CLAMP_TO_EDGE = GL_CLAMP_TO_EDGE;
public static final int REPEAT = GL_REPEAT;
public Texture(URL pngRef) throws IOException {
this(pngRef, GL_NEAREST);
}
public Texture(URL pngRef, int filter) throws IOException {
this(pngRef, filter, GL_REPEAT);
}
public Texture(URL pngRef, int filter, int wrap) throws IOException {
InputStream input = null;
try {
//get an InputStream from our URL
input = pngRef.openStream();
//initialize the decoder
PNGDecoder dec = new PNGDecoder(input);
//set up image dimensions
width = dec.getWidth();
height = dec.getHeight();
//System.out.println(width + "/" + height);
//we are using RGBA, i.e. 4 components or "bytes per pixel"
final int bpp = 4;
//create a new byte buffer which will hold our pixel data
ByteBuffer buf = BufferUtils.createByteBuffer(bpp * width * height);
//decode the image into the byte buffer, in RGBA format
dec.decode(buf, width * bpp, PNGDecoder.Format.RGBA);
//flip the buffer into "read mode" for OpenGL
buf.flip();
//enable textures and generate an ID
glEnable(target);
id = glGenTextures();
//bind texture
bind();
//setup unpack mode
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
//setup parameters
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap);
//pass RGBA data to OpenGL
glTexImage2D(target, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
} finally {
if (input != null) {
try { input.close(); } catch (IOException e) { }
}
}
}
public void bind() {
glBindTexture(target, id);
}
}
長方形クラス:
package com.nightfall.morningside.geometry;
public class Rectangle {
private float x1;
private float y1;
private float width;
private float height;
public Rectangle(float xone, float yone, float w, float h){
x1 = xone;
y1 = yone;
width = w;
height = h;
}
public float getX1(){
return x1;
}
public float getY1(){
return y1;
}
public float getHeight(){
return height;
}
public float getWidth(){
return width;
}
public Point getLocation(){
return new Point(x1, y1);
}
}
ポイントクラス:
package com.nightfall.morningside.geometry;
public class Point {
private float x1;
private float y1;
public Point(float x, float y){
x1 = x;
y1 = y;
}
public float getX(){
return x1;
}
public float getY(){
return y1;
}
}
そして Color クラス:
package com.nightfall.morningside.windowingtoolkit;
public class Colour {
public static final Colour RED = new Colour(1.0f, 0.0f, 0.0f);
public static final Colour GREEN = new Colour(0.0f, 1.0f, 0.0f);
public static final Colour BLUE = new Colour(0.0f, 0.0f, 1.0f);
public static final Colour ORANGE = new Colour(1.0f, 0.5f, 0.0f);
public static final Colour YELLOW = new Colour(1.0f, 1.0f, 0.0f);
public static final Colour PURPLE = new Colour(0.5f, 0.0f, 0.5f);
public static final Colour PINK = new Colour(1.0f, (192 / 255), (203 / 255));
public static final Colour BLACK = new Colour(0.0f, 0.0f, 0.0f);
public static final Colour WHITE = new Colour(1.0f, 1.0f, 1.0f);
public static final Colour MAROON = new Colour(0.36f, 0.0f, 0.0f);
float r;
float g;
float b;
float a;
public Colour(float red, float green, float blue){
this(red, green, blue, 1.0f);
}
public Colour(float red, float green, float blue, float alpha){
r = red;
g = green;
b = blue;
a = alpha;
}
public Colour(int red, int green, int blue){
this(red, green, blue, 100);
}
public Colour(int red, int green, int blue, int alpha){
r = red / 255;
g = green / 255;
b = blue / 255;
a = alpha / 100;
}
public float getRed(){
return r;
}
public float getGreen(){
return g;
}
public float getBlue(){
return b;
}
public float getAlpha(){
return a;
}
public int getRedInt(){
return (int) r * 255;
}
public int getGreenInt(){
return (int) g * 255;
}
public int getBlueInt(){
return (int) b * 255;
}
public int getAlphaInt(){
return (int) a * 255;
}
public void darken(float s){
s = 1-s;
r *= s;
g *= s;
b *= s;
}
public void brighten(float s){
s++;
r *= s;
g *= s;
b *= s;
}
}
私の問題に関連するのはこれらのクラスだけだと思います - 他のすべては無関係です。基本的に、Immediate Mode を使用したときのようにテクスチャがレンダリングされず、煩わしくなります。助けていただければ幸いです。これらのメソッドが廃止された場合はお知らせください。インターネットで drawArray に関するチュートリアルをたくさん見たことがあります。
必要なものがあればお知らせください。投稿します。
また、drawTexturedRectangle が呼び出されたときに表示される四角形は私のやり方です。これは、座標を混乱させたかどうかを確認するためでした。