lwjglgamedev / lwjglbook-leg Goto Github PK
View Code? Open in Web Editor NEWSource code of the chapters of the book 3D Game Development with LWJGL 3
Home Page: https://ahbejarano.gitbook.io/lwjglgamedev/
License: Apache License 2.0
Source code of the chapters of the book 3D Game Development with LWJGL 3
Home Page: https://ahbejarano.gitbook.io/lwjglgamedev/
License: Apache License 2.0
I'm having a bit of trouble with rendering shadows where the shadow map gets distorted in a very strange way. I've compared my code with the sources from the tutorial, and I haven't found any differences other than how the models are batched together. I was working on trying to fix this issue for around 4 hours, but couldn't find any working solutions.
I'm currently looking at game-c26. Am I missing something or are there a lot of assets in the resources folder of that module that aren't being used when running the code?
When i run my thread with Thread.start() my screen not update
Edt1: Sorry my english
Edt: I`m using Windows 10
public class Exemple02_GameLoop implements Runnable{
private long _windowId;
private static final short WIDTH = 800;
private static final short HEIGHT = 600;
private static final String WINDOW_TITLE = "Minha Janela";
private final Thread thread = new Thread(this,"Exemple02_GameLoop");
public static void main(String[] args) {
Exemple02_GameLoop app = new Exemple02_GameLoop();
app.initGLFW();
app.createWindow(WIDTH,HEIGHT,WINDOW_TITLE);
app.setVSync(true);
app.start();
}
public void initGLFW() {
if(!GLFW.glfwInit()) {
System.err.println("Failed to inicialize GLFW!");
System.exit(-1);
}
GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_FALSE);
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
}
public void createWindow(short width, short height, String windowTitle) {
_windowId = GLFW.glfwCreateWindow(width, height, windowTitle, 0, 0);
if(_windowId == 0) { System.err.println("Failed to create Window"); }
GLFW.glfwMakeContextCurrent(_windowId);
GL.createCapabilities();
GLFW.glfwShowWindow(_windowId);
}
public void setVSync(boolean state) {
byte interval = (byte) (state == true? 0:1);
GLFW.glfwSwapInterval(interval);
GLFW.glfwSwapBuffers(_windowId);
}
private synchronized void start() {
thread.start();
}
@Override
public void run() {
long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
long lastFpsTime = 0;
while(!GLFW.glfwWindowShouldClose(_windowId)){
long now = System.nanoTime();
long updateLength = now - lastLoopTime;
lastLoopTime = now;
double delta = updateLength / ((double)OPTIMAL_TIME);
lastFpsTime += updateLength;
if(lastFpsTime >= 1000000000){
lastFpsTime = 0;
}
render();
update();
}
terminate();
}
private void render() {
System.out.println("Renrering");
}
private void update() {
GLFW.glfwPollEvents();
GLFW.glfwSwapBuffers(_windowId);
}
private synchronized void terminate() {
GLFW.glfwDestroyWindow(_windowId);
GLFW.glfwTerminate();
}
}`
I try to import obj files from MagicaVoxel and from Blender as well. Both have materials.
You can check those here: https://drive.google.com/open?id=1E6g-rqI3QPTFfMnMi90CPjKzcxx9tyYp
What I see when importing from blender:
What I see when importing from MagicaVoxel:
However, both have one material and not that diffuse color. For fun, I tried to export the monkey to FBX, where the diffuse color looks OK.
What can be the problem? Code is the same you wrote.
Hi. As I mentioned in the last few cases, I write my "engine" using your and lots of other tutorials beside each other, to avoid copy-and-pasting. I watch and read everything and try to implement myself.
However, shadows are tricky. On the attached images you can see my problem. You can see my shadow map at the top left (it looks good), and I see no shadows :( Tried different ortho settings, light positions, turning spot and point lights off, etc.
Could you give me some starting point where should I search for the bug, because I rewatched, reread everything at least 10 times, and everything in the code looks good.
Please note that I'm using a laptop instead of my computer, So it may take more lights to slow it down / crash for you. But when I add this code it plays around 30FPS (using chapter 26) This is inside setupLights method.
//Point Light
PointLight[] pointLightList = new PointLight[5];
for(int i = 0; i < 5; i++) {
lightIntensity = 1.0f;
Vector3f col = new Vector3f(1.0f, 1.0f, 1.0f);
Vector3f pos = new Vector3f(0 + i, 0, 0 + i);
PointLight pointLight = new PointLight(col, pos, lightIntensity);
PointLight.Attenuation att = new PointLight.Attenuation(0.0f, 0.0f, 1.0f);
pointLight.setAttenuation(att);
pointLightList[i] = pointLight;
}
sceneLight.setPointLightList(pointLightList);
Also when creating more than 5, The game give's a Null Pointer Exception.
Thank-you so very much for taking the time to write such an informative book.
I would clarify under what license is the book source code released under ?
I am slightly confused as the book itself mentions that the license is " Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) " but is this for the book material itself or is it for the source code in this GitHub project or for both the book material and the source code ?
Thank-you again
I have been doing a project along with your tutorial (and some things I am doing on my own - multiplayer, etc.), but now I am stuck on chapter 10 with point lights. I just don't know what to do, because I tried changing shaders, copying the code from sources - it doesn't help. Link to repo - https://github.com/AndersonARC-e/graphics, I am using Kotlin language, Java 12 and OpenGL 4.5.
Could you please clarify under which terms readers are allowed to use the example code in this repository?
TY!
I experienced an issue with the terrain being culled off from the opposite viewing direction.
The indices of the terrain are generated in clockwise rotation in HeightMapMesh.java , which is most likely causing this issue.
Changing a few lines from:
indices.add(leftTop);
indices.add(leftBottom);
indices.add(rightTop);
indices.add(rightTop);
indices.add(leftBottom);
indices.add(rightBottom);
to count-clockwise order, happens to solve the problem for me:
indices.add(rightTop);
indices.add(leftBottom);
indices.add(rightBottom);
indices.add(leftTop);
indices.add(leftBottom);
indices.add(rightTop);
Hi, I'm facing a NullPointerException in the Utils.java line 11 (chapter 4 forward), when it try to instantiate the Scanner.
The file of the string 'fileName' is ok.
LOG:
vertex.vs is a true file (my print)
java.lang.NullPointerException: source
at java.util.Objects.requireNonNull(Objects.java:228)
at java.util.Scanner.(Scanner.java:578)
at org.lwjglb.engine.Utils.loadResource(Utils.java:11)
at org.lwjglb.game.Renderer.init(Renderer.java:26)
at org.lwjglb.game.DummyGame.init(DummyGame.java:22)
at org.lwjglb.engine.GameEngine.init(GameEngine.java:50)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:38)
at java.lang.Thread.run(Thread.java:745)
I am fairly new to using LWJGL, and I keep getting this error. From what I can tell from reading under the THREAD section in the log, it seems to crash on Thread.run()
Here is the log file IntelliJ spits out at me: hs_err_pid18639.log
Running the code with Java 8 Update 121, 64 bit version gives the following Exception:
java.lang.ClassCastException: org.lwjglb.engine.graph.Mesh cannot be cast to org.lwjglb.engine.graph.InstancedMesh
at org.lwjglb.engine.graph.Renderer.renderParticles(Renderer.java:201)
This isn't really an issue, but I figured I would let you know. On page 8, code is spelled "codee" below the figure. I will try to post updates as I read through so you can fix issues such as that.
I cloned this project and opened it with Intellij IDEA and everything seems to build nicely, but when I try to run the chapters that include loading resources, the programs throw exceptions:
java.lang.Exception: Image file [textures/grassblock.png] not loaded: Unable to open file
at org.lwjglb.engine.graph.Texture.loadTexture(Texture.java:43)
at org.lwjglb.engine.graph.Texture.<init>(Texture.java:16)
at org.lwjglb.game.DummyGame.init(DummyGame.java:50)
at org.lwjglb.engine.GameEngine.init(GameEngine.java:40)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:27)
at org.lwjglb.game.Main.main(Main.java:13)
java.lang.NullPointerException
at org.lwjglb.game.DummyGame.cleanup(DummyGame.java:114)
at org.lwjglb.engine.GameEngine.cleanup(GameEngine.java:69)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:32)
at org.lwjglb.game.Main.main(Main.java:13)
Did I miss something obvious here? Do I need to manually edit the project configuration files somehow?
Changing absolute path for the texture filenames seems to fix the issue somewhat, but with chapter27 and Assimp aiImportFile
seems to return null always.
When I run Chapter 27 part 1 I get the window that shows the house in the top left corner of the screen (this is an unrelated issue with the source code window maximize not working, anyway I just have to click on the maximize button on the window) and after a few seconds (2-3 maybe) the application stops and I get the following message in the console:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff89cdb2503, pid=5188, tid=2228
#
# JRE version: OpenJDK Runtime Environment (11.0+28) (build 11+28)
# Java VM: OpenJDK 64-Bit Server VM (11+28, mixed mode, tiered, compressed oops, g1 gc, windows-amd64)
# Problematic frame:
# C [ntdll.dll+0x12503]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\Users\ramho\eclipse-workspace\lwjglbook\chapter27\c27-p1\hs_err_pid5188.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
I also get the error log :
https://pastebin.com/raw/mWwsNjsW
My system is
Processor Intel(R) Core(TM) i5-9600K CPU @ 3.70GHz
Video Card Intel(R) UHD Graphics 630
Video Card #2 NVIDIA GeForce RTX 2070
RAM 16 GB
Operating System Windows 10
I have not yet try to troubleshoot it. I will post again if I find anything that could cause the issue. I also have similar issues on Chapter 27 part 2 and chapter 28. However part 2 seems to crash without showing any window or even a message.
The Utils class in the engine package contains a method called "loadResource":
public static String loadResource(String fileName) throws Exception {
String result;
try (
InputStream in = Class.forName(Utils.class.getName()).getResourceAsStream(fileName);
Scanner scanner = new Scanner(in, "UTF_8")
) {
result = scanner.useDelimiter("\\A").next();
}
return result;
}
This method could be written prettier:
public static String loadResource(String fileName) throws Exception {
String result;
try (
InputStream in = Utils.class.getResourceAsStream(fileName);
Scanner scanner = new Scanner(in, StandardCharsets.UTF_8)
) {
result = scanner.useDelimiter("\\A").next();
}
return result;
}
Class.forName(Utils.class.getName())
can be replaced with Utils.class
and the string "UTF_8"
can be replaced with StandardCharsets.UTF_8
.
Hi, I've been following your tutorial/book. I've come across an issue that I cannot solve since I don't know where to start. When I use normal mapping on textures with shadow mapping I seem to get a weird shadow under the object. The light direction is going down but when I rotate an object it gets extremely dark and then light with a box underneath.
Any idea to a solution would be amazing, great series and I appreciate the work you have been doing on this.
Also feel free to look into the code I'm using (the shadows implementation isn't at all optimised it's just to get it working). https://github.com/J4D3N/Spartan-Engine
In order to make it easier to keep track of, can you switch each individual chapter to be a new branch rather that a new folder. If someone wants to download source for a specific chapter, it would make life a lot easier that way.
Hey,
it seems that the code is not working properly anymore with the new Java 9 version. They seem to have changed the behaviour of input-streams, so that compiling the input of the shader-files will throw an NPE under Java 9. Java 8 still works fine though.
Is there any chance of an update on this?
In chapter7, at the beginning (creating cube), v6 has the coordinate -0.5f, -0.5f, -0.5f. Why the X coordinate is negative?
I tried to create coordinates by myself and -0.5f, -0.5f, -0.5f is the coordinate of the v7 regarding to the 3D image at the start in the chapter.
I just went through the triangles, and I see that the right face's triangle is 3, 2, 7, which makes no sense, so I think the image is the bad guy here, v6 and v7 is switched(?).
Hi. I'm here again... :)
Just finished the chapter12 with a lot debugging, because at the end, I got just a simple black screen, without any error. Even the ESC or any key input was not working.
Hours later, I've found that I get the black screen, when I initialize the FONT variable in the Hud.java. Tried lots of differents things, but got black screen if I write this line down to anywhere:
new Font("Arial", Font.PLAIN, 20);
Any idea why it brakes on osx?
Good Day
Thank you for this very well made tutorial. I have found an issue with the OBJ-Loader-System:
If you try to load an OBJ-File which has more Texture-Coordinates than Position-Vectors (That happens for example with UV-Maps where you need multiple tex-coords per Vertex), the Loaded Mesh looks very wrong. I have extended the code to handle that case. Maybe something like that could be added to the source?
`package graphics;
import java.util.ArrayList;
import java.util.List;
import org.joml.Vector2f;
import org.joml.Vector3f;
import graphics.FileUtility;
public class OBJLoader {
/**
* Liesst ein OBJ-Modell-File ein und extrahiert daraus alle Daten so, dass man sie als Mesh hat.
* @param fileName Resourcen-Name des Modells.¨
* @param XZNormalize true => Modell so skallieren, dass in der XZ-Ebene der auesserste Punkt die Entfernung 1.0 von der mitte hat...
* @return Fertig geladenes Mesh
* @throws Exception Wenn etwas schieflaeuft.
*/
public static Mesh loadMesh(String fileName, boolean XZNormalize) throws Exception {
//File Zeile fuer Zeile einlesen.
List<String> lines = FileUtility.readAllLines(fileName);
//Grundlisten vorbereiten
List<Vector3f> vertices = new ArrayList<>();
List<Vector2f> textures = new ArrayList<>();
List<Vector3f> normals = new ArrayList<>();
List<Face> faces = new ArrayList<>();
//Zeile fuer Zeile einlesen.
for (String line : lines) {
String[] tokens = line.split("\\s+");
switch (tokens[0]) {
case "v":
// Das ist ein Positionsvektor
Vector3f vec3f = new Vector3f(
Float.parseFloat(tokens[1]),
Float.parseFloat(tokens[2]),
Float.parseFloat(tokens[3]));
vertices.add(vec3f);
break;
case "vt":
// Das ist eine Texturkoordinate
Vector2f vec2f = new Vector2f(
Float.parseFloat(tokens[1]),
Float.parseFloat(tokens[2]));
textures.add(vec2f);
break;
case "vn":
// Das ist ein Normalenvektor
Vector3f vec3fNorm = new Vector3f(
Float.parseFloat(tokens[1]),
Float.parseFloat(tokens[2]),
Float.parseFloat(tokens[3]));
normals.add(vec3fNorm);
break;
case "f":
//Das ist eine Face-Beschreibung. Daraus generiert man den Index-Buffer.
Face face = new Face(tokens[1], tokens[2], tokens[3]);
faces.add(face);
break;
default:
// Ignore other lines
break;
}
}
if (XZNormalize) {
float furthest = 0.0f;
for(Vector3f v : vertices) {
float dist = v.x * v.x + v.z * v.z;
if(dist > furthest) {
furthest = dist;
}
}
float scale = (float)Math.sqrt(furthest);
for(Vector3f v : vertices) {
v.x = v.x / scale;
v.y = v.y / scale;
v.z = v.z / scale;
}
}
//Listen expandieren und ordnen und daraus das Mesh erstellen.
if(vertices.size() >= textures.size()) {
return reorderListsByVerts(vertices, textures, normals, faces);
}
else {
return reorderListsByTexcoords(vertices, textures, normals, faces);
}
}
/**
* Expandiert die kompressierten Listen anhand des Texturbuffers und berechnet den Index-buffer.
* Wir haben das Problem, das OBJ-Files drei Index-Buffers haben.
* Einen fuer Positionen, einen fuer Texturkoordinaten und einer Fuer Normalen.
* OpenGL erlaubt aber nur einen. Der dort gespeicherte Index gilt fuer alle Arrays und alle Arrays
* muessen gleich lang sein. Deshalb muessen die Fehlenden eintraege in
* Textur- und Normalenbuffer nachgerechnet und hinzugefuehgt werden.
* Ausserdem muss die Listenordnung so gemacht werden, dass alle zusammengehoerenden Werte
* jeweils den gleichen Index haben.
*
* @param posList Eingelesene positionsliste
* @param textCoordList Eingelesene Texturkoordinatenliste.
* @param normList Eingelesene Normalenliste.
* @param facesList Eingelesene Facettenliste.
* @return Fertig instantiiertes Mesh.
*/
private static Mesh reorderListsByTexcoords(List<Vector3f> posList, List<Vector2f> textCoordList,
List<Vector3f> normList, List<Face> facesList) {
List<Integer> indices = new ArrayList<Integer>();
//Masterliste ist die mit den texturkoordinaten.
float[] texArr = new float[textCoordList.size() * 2];
int i = 0;
for(Vector2f tex : textCoordList) {
texArr[i*2] = tex.x;
texArr[i*2 + 1] = 1.0f - tex.y;
i++;
}
//Arrays fuer Vertices und Normalenstream erstellen
float[] posArr = new float[textCoordList.size() * 3];
float[] normArr = new float[textCoordList.size() * 3];
//Durch die Facettenliste durchgehen und daraus den Indexbuffer und die Textur/Normalenbuffer rechnen.
for (Face face : facesList) {
IdxGroup[] faceVertexIndices = face.getFaceVertexIndices();
for(IdxGroup indValue : faceVertexIndices) {
processFaceVertexByTexcoord(indValue, posList, normList, indices, posArr, normArr);
}
}
int[] indicesArr = new int[indices.size()];
indicesArr = indices.stream().mapToInt((Integer v) -> v).toArray();
Mesh mesh = new Mesh(posArr, texArr, normArr, indicesArr);
return mesh;
}
/**
* Mappt die Positions- und Normalenvektoren auf den richtigen Platz und
* fuegt den Index hinzu...
* @param indices Indexgruppe
* @param posList Liste mit den Positionsvektoren
* @param normList Liste mit den Normalenvektoren
* @param indicesList Liste mit den Indices.
* @param posArr Array mit den Positionsdaten
* @param normArr Array mit den Normalendaten.
*/
private static void processFaceVertexByTexcoord(IdxGroup indices, List<Vector3f> posList,
List<Vector3f> normList, List<Integer> indicesList,
float[] posArr, float[] normArr) {
int texIndex = indices.idxTextCoord;
indicesList.add(texIndex);
if(indices.idxPos != IdxGroup.NO_VALUE) {
Vector3f pos = posList.get(indices.idxPos);
posArr[texIndex * 3] = pos.x;
posArr[texIndex * 3 + 1] = pos.y;
posArr[texIndex * 3 + 2] = pos.z;
}
if(indices.idxVecNormal != IdxGroup.NO_VALUE) {
//Normale einsetzen(Falls Vorhanden).
Vector3f vecNorm = normList.get(indices.idxVecNormal);
normArr[texIndex * 3] = vecNorm.x;
normArr[texIndex* 3 + 1] = vecNorm.y;
normArr[texIndex* 3 + 2] = vecNorm.z;
}
}
/**
* Expandiert die kompressierten Listen und berechnet den Index-buffer.
* Wir haben das Problem, das OBJ-Files drei Index-Buffers haben.
* Einen fuer Positionen, einen fuer Texturkoordinaten und einer Fuer Normalen.
* OpenGL erlaubt aber nur einen. Der dort gespeicherte Index gilt fuer alle Arrays und alle Arrays
* muessen gleich lang sein. Deshalb muessen die Fehlenden eintraege in
* Textur- und Normalenbuffer nachgerechnet und hinzugefuehgt werden.
* Ausserdem muss die Listenordnung so gemacht werden, dass alle zusammengehoerenden Werte
* jeweils den gleichen Index haben.
*
* @param posList Eingelesene positionsliste
* @param textCoordList Eingelesene Texturkoordinatenliste.
* @param normList Eingelesene Normalenliste.
* @param facesList Eingelesene Facettenliste.
* @return Fertig instantiiertes Mesh.
*/
private static Mesh reorderListsByVerts(List<Vector3f> posList, List<Vector2f> textCoordList,
List<Vector3f> normList, List<Face> facesList) {
List<Integer> indices = new ArrayList<Integer>();
// Positionsvektorliste in ein Array von Floats umwandeln (Format: X, Y, Z, X, Y, Z... So wie fuer Mesh benoetigt)
float[] posArr = new float[posList.size() * 3];
int i = 0;
for (Vector3f pos : posList) {
posArr[i * 3] = pos.x;
posArr[i * 3 + 1] = pos.y;
posArr[i * 3 + 2] = pos.z;
i++;
}
//Arrays fuer Texturkoordinatenstream und Normalenstream erstellen.
float[] textCoordArr = new float[posList.size() * 2];
float[] normArr = new float[posList.size() * 3];
//Durch die Facettenliste durchgehen und daraus den Indexbuffer und die Textur/Normalenbuffer rechnen.
for (Face face : facesList) {
IdxGroup[] faceVertexIndices = face.getFaceVertexIndices();
for (IdxGroup indValue : faceVertexIndices) {
processFaceVertexByVert(indValue, textCoordList, normList, indices, textCoordArr, normArr);
}
}
int[] indicesArr = new int[indices.size()];
indicesArr = indices.stream().mapToInt((Integer v) -> v).toArray();
Mesh mesh = new Mesh(posArr, textCoordArr, normArr, indicesArr);
return mesh;
}
/**
* Einen Eintrag in der Facettenliste verarbeiten.
* @param indices Aktuelle Facette
* @param textCoordList Texturkoordinatenliste
* @param normList Normalenliste
* @param indicesList Indexliste
* @param texCoordArr Finalarray fuer Textur
* @param normArr Finalarray fuer Normalen
*/
private static void processFaceVertexByVert(IdxGroup indices, List<Vector2f> textCoordList,
List<Vector3f> normList, List<Integer> indicesList,
float[] texCoordArr, float[] normArr) {
// Index fuer die Positionsvektoren setzen.
int posIndex = indices.idxPos;
indicesList.add(posIndex);
// Texturkoordinaten einsetzen(falls Vorhenden)
if (indices.idxTextCoord != IdxGroup.NO_VALUE) {
Vector2f textCoord = textCoordList.get(indices.idxTextCoord);
texCoordArr[posIndex * 2] = textCoord.x;
texCoordArr[posIndex * 2 + 1] = 1 - textCoord.y;
}
if (indices.idxVecNormal != IdxGroup.NO_VALUE) {
//Normale einsetzen(Falls Vorhanden).
Vector3f vecNorm = normList.get(indices.idxVecNormal);
normArr[posIndex * 3] = vecNorm.x;
normArr[posIndex * 3 + 1] = vecNorm.y;
normArr[posIndex * 3 + 2] = vecNorm.z;
}
}
/**
* Hilfsklasse die alle Daten fuer eine Facette enthaelt.
*/
protected static class Face {
/**
* Die Indexgruppenliste fuer ein Dreieck.
*/
private IdxGroup[] idxGroups = new IdxGroup[3];
public Face(String v1, String v2, String v3) {
idxGroups = new IdxGroup[3];
//Die Zeilen aus dem Textfile umwandeln.
idxGroups[0] = parseLine(v1);
idxGroups[1] = parseLine(v2);
idxGroups[2] = parseLine(v3);
}
/**
* Extrahiert die Indexgruppendaten aus einer Textzeile.
* @param Zu verarbeitende Textzeile
* @return IdxGroup Hilfsklasse mit den geladenen Daten.
*/
private IdxGroup parseLine(String line) {
IdxGroup idxGroup = new IdxGroup();
String[] lineTokens = line.split("/");
int length = lineTokens.length;
idxGroup.idxPos = Integer.parseInt(lineTokens[0]) - 1;
if (length > 1) {
String textCoord = lineTokens[1];
idxGroup.idxTextCoord = textCoord.length() > 0 ? Integer.parseInt(textCoord) - 1 : IdxGroup.NO_VALUE;
if (length > 2) {
idxGroup.idxVecNormal = Integer.parseInt(lineTokens[2]) - 1;
}
}
return idxGroup;
}
public IdxGroup[] getFaceVertexIndices() {
return idxGroups;
}
}
/**
* Hilfsklasse die eine Indexgruppe darstellt.
* Eine Indexgruppe besteht aus folgenden Eintraegen:
* Index auf die Positionsinformation
* Index auf die texturkoordinaten
* Index auf die Normale
*
*/
protected static class IdxGroup {
public static final int NO_VALUE = -1;
public int idxPos;
public int idxTextCoord;
public int idxVecNormal;
public IdxGroup() {
idxPos = NO_VALUE;
idxTextCoord = NO_VALUE;
idxVecNormal = NO_VALUE;
}
}
}
`
Have a nice day.
In chapter 2, you have a Scanner allocated in memory, but never close it. Without closing it, memory will leak. I recommend this: PasteBin
I'm getting "java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl_opengl.dll" on windows.
Issue is fixed by adding
<dependency>
<groupId>org.lwjgl</groupId>
<artifactId>lwjgl-opengl</artifactId>
<version>${lwjgl.version}</version>
<classifier>${native.target}</classifier>
<scope>runtime</scope>
</dependency>
to chapter01 pom.xml .
java.lang.Exception: Error loading model
at org.lwjglb.engine.loaders.assimp.StaticMeshesLoader.load(StaticMeshesLoader.java:45)
at org.lwjglb.engine.loaders.assimp.StaticMeshesLoader.load(StaticMeshesLoader.java:37)
at org.lwjglb.game.DummyGame.init(DummyGame.java:72)
at org.lwjglb.engine.GameEngine.init(GameEngine.java:65)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:52)
at java.lang.Thread.run(Unknown Source)
Since version 1.8.0 (released on June 3, 2016) JOML's Matrix4f class can unproject from window coordinates via unprojectRay()
and unprojectInvRay()
.
The MouseBoxSelectionDetector.selectGameItem()
can be simplified then.
Hi, just a comment. I've started to read the OpenGL red book, and there are a lot of new stuff people can use, but none of the existing tutorials cover.
For example:
Here is my repo where I use these, feel free to use it to update your tutorials: https://github.com/mudlee/intermetto2D
I commit only, when everything is running fine. BTW, it will be (ever?) a 2D platformer, nothing special :)
Since there is no way to send messages to users I'll just leave a lil' cheers here. Feel free to close this "issue" ;)
Hi!
I'm just wondering that in the tutorial, directional- and pointligths are handling the material reflectivity in the fragment shader as I expected. My question is: why the spotlight calculation does not? So if I light an object with only a spotlight, it does not matter how reflective it is?
Thanks.
BTW, this tutorial is a must for people who start learning lwjgl. Cannot say enough, thank you guy(s)! Well written, well done material!
Hello, I've tried creating a Terrain on Chapter 26, And Chapter 25. It works fine, But the Terrain is vanishing when it shouldn't, Am I doing something wrong?
I added this into the init method in DummyGame class
float terrainScale = 10;
//int terrainSize = 3;
int terrainSize = 3;
float minY = -0.1f;
float maxY = 0.1f;
int textInc = 40;
terrain = new Terrain(terrainSize, terrainScale, minY, maxY, "/textures/heightmap.png", "/textures/terrain.png", textInc);
scene.setGameItems(terrain.getGameItems());
Firstly, loving the book - keep at it!
I had an issue working through the particle chapter where the particles were always being rendered at the camera location (and they would move with me).
I figured out that the cause was due to the viewMatrix being altered in the renderSkyBox method (as I still had my SkyBox enabled).
Swapping the render order so that the particles rendered before the SkyBox didn't work, however rebuilding the viewMatrix in the renderParticles method corrects the viewMatrix and everything appears to render correctly from there on.
Keep up the good work and I look forward to future chapters.
#Edit: I'm an idiot. The renderSkyBox method stores and resets the values so the rebuild is not require.
Hi, I am getting a NullPointerException but am not entirely sure why.
Error log:
java.lang.NullPointerException
at com.harryradford.game.DummyGame.cleanup(DummyGame.java:194)
at com.harryradford.engine.GameEngine.cleanup(GameEngine.java:77)
at com.harryradford.engine.GameEngine.run(GameEngine.java:41)
at java.lang.Thread.run(Thread.java:748)
at com.harryradford.engine.GameEngine.start(GameEngine.java:27)
at com.harryradford.game.Main.main(Main.java:13)
Zipped project:
Ch7lwjglbook.zip
I took practically all the code in chapter 15 and implemented it into my application but I'm getting this exception when I try to run the application.
Any ideas about why this is happening? I also tried building chapter 15 with mvn and the build fails so I can't test the application directly.
maven gives this error:
Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:compile (default-compile) on project game-c15: Fatal error compiling: invalid target release: 9 -> [Help 1]
This might be just me, but when I downloaded the source files for the first chapter of your book, maven refused to build the project with a NonResolveableParentPOM
error. I then just copied and pasted most of the code from https://github.com/lwjglgamedev/lwjglbook/blob/master/pom.xml into my local POM, and it works now. I just wanted to make you aware of the matter.
At the insideFrustum calculation in chapter Optimizations - Frustum Culling (I) plane.z is multiplied with x0 instead of z0 which leads to not correctly rendered game items.
I don't know if this only happens when I run the code, but when a GameItem's rotation is modified, the light angle renders incorrectly (I tested it using a sphere made up of triangles so that the problem was more obvious). When the camera changes rotation the light direction renders fine, but if you make a GameItem constantly shift rotation the light seems to wobble up and down the object (depending on the position of the light), creating an undesired effect that makes the scene less realistic since one item has a different lighting than the rest. This problem is the same for all types of lights discussed in the book, but it doesn't affect the shadows. I know that the chapters after lighting was implemented did not involve any rotation, so it doesn't affect the examples in the book. However, if others try to use your shaders and rotate their GameItems, their programs will be flawed as well. I hope that you can fix this problem since I don't possess the LWJGL knowledge to fix this problem myself - I can only suspect that the problem has to do with the vertex shader and the fragment shader, but not the exact location of the problem itself.
Regardless of that, I think that your book is very well-written and explains LWJGL better than anything else on the internet. Thank you for taking the time to put something like this together. I hope you understand the cause of this problem more than I do.
As I have been reading through the book, I have a few ideas for future chapters that you can add (solely graphics).
Hi I have been having an issue with textures after importing them from Blender. The textures look good inside of blender but when they are in my game they are all distorted. I have tried multiple things to fix this issue but have had no luck. I also made sure all export settings from blender was the same as you said. My code is currently up to date with chapter 15. I have attached the .obj file for the model and a picture of the distorted texture. To test the problem I made a model in Blender (a cube) and UV mapped the grass block texture you supplied. I also compared the model I created to the block.obj model you supplied and while there were difference between some
values I don't think they are causing the issue. It should be noted that when using block.obj you supplied the texture looks perfect. Thanks so much for your help and for creating this book. I greatly appreciate it!
# Blender v2.78 (sub 0) OBJ File: '' o Cube v -1.000000 -1.000000 1.000000 v -1.000000 1.000000 1.000000 v -1.000000 -1.000000 -1.000000 v -1.000000 1.000000 -1.000000 v 1.000000 -1.000000 1.000000 v 1.000000 1.000000 1.000000 v 1.000000 -1.000000 -1.000000 v 1.000000 1.000000 -1.000000 vt -0.0053 0.9992 vt 0.4953 0.4986 vt -0.0053 0.4986 vt 0.4965 1.0004 vt -0.0025 0.5014 vt 0.4965 0.5014 vt -0.0044 1.0003 vt 0.4943 0.5016 vt -0.0044 0.5016 vt 0.4976 1.0015 vt -0.0076 0.4963 vt 0.4976 0.4963 vt 0.9976 0.5022 vt 0.5002 0.9996 vt 0.5002 0.5022 vt 0.0001 0.5001 vt 0.4980 0.0022 vt 0.4980 0.5001 vt 0.4953 0.9992 vt -0.0025 1.0004 vt 0.4943 1.0003 vt -0.0076 1.0015 vt 0.9976 0.9996 vt 0.0001 0.0022 vn -1.0000 0.0000 0.0000 vn 0.0000 0.0000 -1.0000 vn 1.0000 0.0000 0.0000 vn 0.0000 0.0000 1.0000 vn 0.0000 -1.0000 0.0000 vn 0.0000 1.0000 0.0000 s off f 2/1/1 3/2/1 1/3/1 f 4/4/2 7/5/2 3/6/2 f 8/7/3 5/8/3 7/9/3 f 6/10/4 1/11/4 5/12/4 f 7/13/5 1/14/5 3/15/5 f 4/16/6 6/17/6 8/18/6 f 2/1/1 4/19/1 3/2/1 f 4/4/2 8/20/2 7/5/2 f 8/7/3 6/21/3 5/8/3 f 6/10/4 2/22/4 1/11/4 f 7/13/5 5/23/5 1/14/5 f 4/16/6 2/24/6 6/17/6
typo in Timer class of chapter 2:
public float getEllapsedTime() {
In the following code:
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
if (opts.compatibleProfile) {
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
} else {
// Here
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
}
If the else block is executed, an exception is thrown when the renderCrossHair function call the LWJGL's glPushMatrix native function. The exception is due to the fact that glPushMatrix is not available in compat mode.
Error message: No context is current or a function that is not available in the current context was called
Just a proposal: Pngdecoder is very outdated, and we can use STB very easily.
https://github.com/SilverTiger/lwjgl3-tutorial/wiki/Textures
I receive this error when I try to run Chapter 2 of your code:
Building game-c02 1.0
--- exec-maven-plugin:1.2.1:exec (default-cli) @ game-c02 ---
[LWJGL] GLFW_VERSION_UNAVAILABLE error
Description : WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable
Stacktrace :
org.lwjgl.glfw.GLFW.nglfwCreateWindow(GLFW.java:1361)
org.lwjgl.glfw.GLFW.glfwCreateWindow(GLFW.java:1521)
org.lwjglb.engine.Window.init(Window.java:53)
org.lwjglb.engine.GameEngine.init(GameEngine.java:44)
org.lwjglb.engine.GameEngine.run(GameEngine.java:36)
java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: Failed to create the GLFW window
at org.lwjglb.engine.Window.init(Window.java:55)
at org.lwjglb.engine.GameEngine.init(GameEngine.java:44)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:36)
at java.lang.Thread.run(Thread.java:748)
I am using LWJGL 3.1.2 build 29, on NetBeans IDE 8.2. The only change I made to the code is that I commented out the glfwWindowHints code in the Window class file.
I need a little help here. Examples build fine, however if running first example, it stops with the following error below. Neither natives.version set to 0.0.6 nor 0.0.7 helps. Any ideas?
Hello LWJGL 3.0.0 build 87!
[LWJGL] Version: 3.0.0 build 87
[LWJGL] OS: Windows 10 v10.0
[LWJGL] JRE: 1.8.0_92 amd64
[LWJGL] JVM: Java HotSpot(TM) 64-Bit Server VM v25.92-b14 by Oracle Corporation
[LWJGL] Loading library (system): lwjgl
[LWJGL] Loaded from java.library.path: target\natives\lwjgl.dll
[LWJGL] Loading library: glfw
[LWJGL] ThreadLocalUtil state: UnsafeState
[LWJGL] MemoryUtil accessor: MemoryAccessorUnsafe
[LWJGL] Using SharedLibraryLoader...
[LWJGL] Extracting: file:/C:/Users/Piotr/.m2/repository/org/lwjgl/lwjgl-platform/3.0.0-SNAPSHOT/lwjgl-platform-3.0.0-SNAPSHOT-natives-windows.jar!/glfw.dll
java.lang.UnsatisfiedLinkError: Failed to load library: target\natives\glfw.dll (error code = 126)
at org.lwjgl.system.windows.WindowsLibrary.(WindowsLibrary.java:36)
at org.lwjgl.system.APIUtil.apiCreateLibrary(APIUtil.java:110)
at org.lwjgl.system.Library.loadNative(Library.java:187)
at org.lwjgl.system.Library.loadNativeRelative(Library.java:163)
at org.lwjgl.system.Library.loadNative(Library.java:141)
at org.lwjgl.glfw.GLFW.(GLFW.java:562)
at org.lwjglb.game.Main.init(Main.java:44)
at org.lwjglb.game.Main.run(Main.java:25)
at org.lwjglb.game.Main.main(Main.java:115)
[LWJGL] Failed to load a library. Possible solutions:
a) Set -Djava.library.path or -Dorg.lwjgl.librarypath to the directory that contains the shared libraries.
b) Add the JAR(s) containing the shared libraries to the classpath.
Exception in thread "main" java.lang.NoClassDefFoundError: Could not initialize class org.lwjgl.glfw.GLFW
at org.lwjglb.game.Main.run(Main.java:33)
at org.lwjglb.game.Main.main(Main.java:115)
First of all thank you for your book and source code. It's great work and I'm grateful you for this. :)
Unfortunately I discovered some issues:
Hey there,
i have followed your Tutorial and I am stuck on the Chapter with the normal Mapping. When i execute my Program, the GUI will open and i see a black screen like this:
I have looked at the Source of Chapter 17 and i see no differences in my code that should be problematic.
Link to the Repository: https://github.com/simagdo/3DGameEngine
Currently I am using Java 13 and OpenGL 3.1.2
There is an error due to the fact that textures are in the jar and stb wants absolute paths. In the following code:
URL url = Texture.class.getResource("/textures/heightmap.png");
// Crashes
File file = Paths.get(url.toURI()).toFile();
The function Paths.get(URI) throws an FileSystemNotFoundException.
The same problem is present in the Texture class.
The program launches very well in IntelliJ IDEA since it does not build a jar, but if you use Maven to build one and launch it, it crashes.
Hi, I am at a loss here. While working on my own code I noticed I am not able to use the assimp function aiImportFile(resourcePath, flags); to load models when running the jar from the cmd line. It works well when inside eclipse or even in RenderDoc. I build the jar and copied the models and textures folders inside the target folder to have them adjacent to the jar but this is the error I get. Did I miss an obvious step?
C:\Users\ramho\Desktop>java -jar F:\GIT\lwjglb\lwjglbook\chapter28\target\game-c28-1.0.jar
java.lang.Exception: Error loading model [resourcePath: models/buffer_pass_mess.obj, texturesDir:models]
at org.lwjglb.engine.loaders.assimp.StaticMeshesLoader.load(StaticMeshesLoader.java:44)
at org.lwjglb.engine.loaders.assimp.StaticMeshesLoader.load(StaticMeshesLoader.java:36)
at org.lwjglb.engine.graph.Renderer.init(Renderer.java:85)
at org.lwjglb.game.DummyGame.init(DummyGame.java:57)
at org.lwjglb.engine.GameEngine.init(GameEngine.java:53)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:40)
at org.lwjglb.game.Main.main(Main.java:20)
java.lang.NullPointerException
at org.lwjglb.game.DummyGame.cleanup(DummyGame.java:200)
at org.lwjglb.engine.GameEngine.cleanup(GameEngine.java:84)
at org.lwjglb.engine.GameEngine.run(GameEngine.java:45)
at org.lwjglb.game.Main.main(Main.java:20)
It would be better that in the package main.java.org.lwjglb.engine
, the 'protected void render()' method of the class GameEngine
protected void render() {
···· gameLogic.render(window);
···· window.update();
}
, looks like this:
protected void render() {
···· glfwPollEvents();
···· gameLogic.render(window);
···· glfwSwapBuffers(window);
}
If not, there may be render problems.
Regards.
P.S. An outstanding book!
Error compiling Shader code: 0:167(2): error: return' with wrong type int, in function
calcShadow' returning float
Solution:
In scene_fragment.fs, in calcShadow change return types from 1 to 1.0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.