我正在使用Java LWJGL和OpenGL创建一个3D游戏。我希望能够在屏幕上显示玩家健康栏。我正在考虑在渲染游戏后可以呈现的某种屏幕,它将处理所有类似于2D的用户界面。需要渲染到屏幕的元素。这样做的最佳做法是什么?我尝试使用Graphics类创建一个Screen类和绘画,但我遇到了这个问题。我想要一个简单的方法来渲染这些元素。怎么做的?
编辑:
以下是我认为有用的一些文件
MasterRenderer:
package renderEngine;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import models.TexturedModel;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.vector.Matrix4f;
import shaders.StaticShader;
import shaders.TerrainShader;
import terrains.Terrain;
import entities.Camera;
import entities.Entity;
import entities.Light;
public class MasterRenderer {
private static final float FOV = 70;
private static final float NEAR_PLANE = 0.1f;
private static final float FAR_PLANE = 1000;
private static final float RED = 0.5f;
private static final float GREEN = 0.90f;
private static final float BLUE = 0.90f;
private GUI gui = new GUI();
private Matrix4f projectionMatrix;
private StaticShader shader = new StaticShader();
private EntityRenderer renderer;
private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
private List<Terrain> terrains = new ArrayList<Terrain>();
private TerrainRenderer terrainRenderer;
private TerrainShader terrainShader = new TerrainShader();
public MasterRenderer() {
enableCulling();
createProjectionMatrix();
renderer = new EntityRenderer(shader, projectionMatrix);
terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);
}
public static void enableCulling() {
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glCullFace(GL11.GL_BACK);
}
public static void disableCulling() {
GL11.glDisable(GL11.GL_CULL_FACE);
}
public void prepare() {
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT|GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(RED, GREEN, BLUE, 1);
}
public void render(Light sun, Camera camera) {
prepare();
shader.start();
shader.loadSkyColour(RED,GREEN,BLUE);
shader.loadLight(sun);
shader.loadViewMatrix(camera);
renderer.render(entities);
shader.stop();
terrainShader.start();
terrainShader.loadLight(sun);
terrainShader.loadViewMatrix(camera);
terrainShader.loadSkyColour(RED,GREEN,BLUE);
terrainRenderer.render(terrains);
terrainShader.stop();
gui.drawRect(100, 100, 300, 300, 0x00000000);
terrains.clear();
entities.clear();
}
public void processTerrain(Terrain terrain) {
terrains.add(terrain);
}
public void processEntity(Entity entity) {
TexturedModel entityModel = entity.getModel();
List<Entity> batch = entities.get(entityModel);
if(batch != null) {
batch.add(entity);
} else {
List<Entity> newBatch = new ArrayList<Entity>();
newBatch.add(entity);
entities.put(entityModel, newBatch);
}
}
private void createProjectionMatrix() {
float aspectRatio = (float) Display.getWidth() / (float) Display.getHeight();
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspectRatio);
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
projectionMatrix = new Matrix4f();
projectionMatrix.m00 = x_scale;
projectionMatrix.m11 = y_scale;
projectionMatrix.m22 = -((FAR_PLANE + NEAR_PLANE) / frustum_length);
projectionMatrix.m23 = -1;
projectionMatrix.m32 = -((2 * NEAR_PLANE * FAR_PLANE) / frustum_length);
projectionMatrix.m33 = 0;
}
public void cleanUp() {
shader.cleanUp();
terrainShader.cleanUp();
}
}
Camera.java:
package entities;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.vector.Vector3f;
public class Camera {
private float distanceFromPlayer = 50;
private float angleAroundPlayer = 0;
private Vector3f position = new Vector3f(0,0,0);
private float pitch = 20; //rotation
private float yaw = 0; //left or right
private float roll; //Tilted
private Player player;
public Camera(Player player) {
this.player = player;
}
public void move() {
calculateZoom();
calculatePitch();
calculateAngleAroundPlayer();
float horizontalDistance = calculateHorizontalDistance();
float verticalDistance = calculateVerticalDistance();
calculateCameraPosition(horizontalDistance, verticalDistance);
this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
}
public float getAngleAroundPlayer() {
return angleAroundPlayer;
}
public Vector3f getPosition() {
return position;
}
public float getPitch() {
return pitch;
}
public float getYaw() {
return yaw;
}
public float getRoll() {
return roll;
}
public void setAngleAroundPlayer(float angleAroundPlayer) {
this.angleAroundPlayer = angleAroundPlayer;
}
private void calculateCameraPosition(float horizDistance, float verticDistance) {
float theta = player.getRotY() + angleAroundPlayer;
float offsetX = (float) (horizDistance * Math.sin(Math.toRadians(theta)));
float offsetZ = (float) (horizDistance * Math.cos(Math.toRadians(theta)));
position.x = player.getPosition().x - offsetX;
position.z = player.getPosition().z - offsetZ;
position.y = player.getPosition().y + verticDistance + 10;
}
private float calculateHorizontalDistance() {
return (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch)));
}
private float calculateVerticalDistance() {
return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch)));
}
private void calculateZoom() {
float zoomLevel = Mouse.getDWheel() * 0.1f;
distanceFromPlayer -= zoomLevel;
}
private void calculatePitch() {
if(Mouse.isButtonDown(1)) {
float pitchChange = Mouse.getDY() * 0.1f;
pitch -= pitchChange;
if(pitch < 10) pitch = 10;
if(pitch > 90) pitch = 90;
}
}
private void calculateAngleAroundPlayer() {
if(Mouse.isButtonDown(0)) {
float angleChange = Mouse.getDX() * 0.3f;
if(angleAroundPlayer >= 360) angleAroundPlayer = 0;
angleAroundPlayer -= angleChange;
}
}
}
MainGameLoop:
package engineTester;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import models.TexturedModel;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.vector.Vector3f;
import renderEngine.DisplayManager;
import renderEngine.Loader;
import renderEngine.MasterRenderer;
import renderEngine.OBJLoader;
import terrains.Terrain;
import textures.ModelTexture;
import textures.TerrainTexture;
import textures.TerrainTexturePack;
import toolbox.KeyBindings;
import entities.Camera;
import entities.Entity;
import entities.Light;
import entities.Player;
public class MainGameLoop {
public static KeyBindings keyBindings;
public static Camera camera;
public static void main(String[] args) {// TODO Auto-generated method stub
DisplayManager.createDisplay();
Loader loader = new Loader();
//--------------------Terrain Texture------------------//
TerrainTexture backgroundTexture = new TerrainTexture(loader.loadTexture("grassy2"));
TerrainTexture rTexture = new TerrainTexture(loader.loadTexture("mud"));
TerrainTexture gTexture = new TerrainTexture(loader.loadTexture("pinkFlowers"));
TerrainTexture bTexture = new TerrainTexture(loader.loadTexture("stone"));
TerrainTexturePack texturePack = new TerrainTexturePack(backgroundTexture, rTexture,
gTexture, bTexture);
TerrainTexture blendMap = new TerrainTexture(loader.loadTexture("blendMap"));
//-----------------------------------------------------//
ModelTexture fernTextureAtlas = new ModelTexture(loader.loadTexture("fern"));
fernTextureAtlas.setNumberOfRows(2);
TexturedModel tree1 = new TexturedModel(OBJLoader.loadObjModel("tree", loader),
new ModelTexture(loader.loadTexture("tree")));
TexturedModel tree2 = new TexturedModel(OBJLoader.loadObjModel("lowPolyTree", loader),
new ModelTexture(loader.loadTexture("lowPolyTree")));
TexturedModel fern = new TexturedModel(OBJLoader.loadObjModel("fern", loader),
fernTextureAtlas);
TexturedModel flower = new TexturedModel(OBJLoader.loadObjModel("grassModel", loader),
new ModelTexture(loader.loadTexture("flower")));
TexturedModel stall = new TexturedModel(OBJLoader.loadObjModel("stall", loader),
new ModelTexture(loader.loadTexture("stallTexture")));
TexturedModel grass = new TexturedModel(OBJLoader.loadObjModel("grassModel", loader),
new ModelTexture(loader.loadTexture("grassTexture")));
TexturedModel playerModel = new TexturedModel(OBJLoader.loadObjModel("person", loader),
new ModelTexture(loader.loadTexture("playerTexture")));
grass.getTexture().setUseFakeLighting(true);
grass.getTexture().setHasTransparency(true);
fern.getTexture().setUseFakeLighting(true);
fern.getTexture().setHasTransparency(true);
stall.getTexture().setShineDamper(10);
stall.getTexture().setReflectivity(1);
tree1.getTexture().setShineDamper(10);
Light light = new Light(new Vector3f(0, 20000, 20000), new Vector3f(1,1,1));
Terrain terrain = new Terrain(0, 0, loader, texturePack, blendMap, "heightMap");
List<Entity> entities = new ArrayList<Entity>();
Random random = new Random();
for (int i = 0; i < 400; i++) {
if (i % 2 == 0) {
float x = random.nextFloat() * 800;
float z = random.nextFloat() * 600;
float y = terrain.getHeightOfTerrain(x, z);
entities.add(new Entity(fern, random.nextInt(4), new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, 0.9f));
}
if (i % 5 == 0) {
float x = random.nextFloat() * 800;
float z = random.nextFloat() * 600;
float y = terrain.getHeightOfTerrain(x, z);
entities.add(new Entity(tree1, new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, random.nextFloat() * 1 + 4));
x = random.nextFloat() * 800;
z = random.nextFloat() * 600;
y = terrain.getHeightOfTerrain(x, z);
entities.add(new Entity(tree2, new Vector3f(x, y, z), 0, random.nextFloat() * 360, 0, random.nextFloat() * 0.1f + 0.6f));
}
if (i % 4 == 0) {
float x = random.nextFloat() * 800;
float z = random.nextFloat() * 600;
float y = terrain.getHeightOfTerrain(x, z);
entities.add(new Entity(grass, new Vector3f(x, y, z), 0, 0, 0, 1.5f));
x = random.nextFloat() * 800;
z = random.nextFloat() * 600;
y = terrain.getHeightOfTerrain(x, z);
entities.add(new Entity(flower, new Vector3f(x, y, z), 0, 0, 0, 1.5f));
}
}
MasterRenderer renderer = new MasterRenderer();
Player.parsePlayerData();
float terrainHeight = Player.getTerrainHeight(terrain, Player.PLAYER_X, Player.PLAYER_Z);
Player player = new Player(playerModel, new Vector3f(Player.PLAYER_X, terrainHeight, Player.PLAYER_Z), 0, 0, 0, 1);
camera = new Camera(player);
while (!Display.isCloseRequested()) {
camera.move();
player.move(terrain);
renderer.processEntity(player);
renderer.processTerrain(terrain);
for(Entity entity : entities) {
renderer.processEntity(entity);
}
renderer.render(light, camera);
DisplayManager.updateDisplay();
keyBindings.run();
}
renderer.cleanUp();
loader.cleanUp();
Player.savePlayerData(player/*new Vector3f(player.getPosition().x, terrainHeight, player.getPosition().z)*/);
DisplayManager.closeDisplay();
}
}
答案 0 :(得分:0)
使用透视投影渲染3D场景后,您可以切换到正交投影并将2D图形渲染到其他所有内容之上。在您的情况下,Screen
类非常适合UI呈现。
Game.render(); //Set Persp Proj; Render 3D world (terrain, meshes & models)
Screen.render(); //Set Orhto Proj; Render UI elements on top (textures, fonts)
实际上这个想法非常简单,困难的部分就是在OpenGL版本和编程语言的实现细节中。