我一直在尝试在 lwjgl 中制作一个简单的渲染引擎,但我遇到了一个问题。我离开了即时模式并决定使用 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;
}
}
和颜色类:
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;
}
}
我认为这些课程是唯一与我的问题相关的课程 - 其他一切都无关紧要。所以基本上,纹理不会像使用即时模式时那样渲染,而且越来越烦人。感谢您的帮助,如果不推荐使用这些方法,请告诉我,因为我在 Internet 上看到了很多关于 drawArrays 的教程。
如果您需要任何东西,请告诉我,我会发布。
此外,调用 drawTexturedRectangle 时显示的矩形是我在做的——它是为了看看我是否混淆了我的坐标。