Giter Club home page Giter Club logo

lwjglbook-leg's People

Contributors

71m024 avatar ajikozau avatar darafsa avatar hoijui avatar httpdigest avatar incognitojam avatar insprill avatar jpwrunyan avatar lever1209 avatar lwjglgamedev avatar mbaeuerle avatar neomonkeus avatar oilboi avatar ramh5 avatar rubbaboy avatar zenlambda avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lwjglbook-leg's Issues

Problems with shadows

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.
image

game-c26

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?

GameLoop Thread

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();
}

}`

Assimp importing problem

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:

  • The importer always says that the diffuse color is 0.6-0.6-0.6 which is simply not true
  • It has two materials

What I see when importing from MagicaVoxel:

  • The importer always says that the diffuse color is 0.6-0.6-0.6 which is simply not true
  • It has two materials

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.

Shadow map question

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.

shadowthing
shadowthing2

Slow FPS / Not loading with very few Point Lights

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.

License for source code

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

Problem with point ligths

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.

Example code license?

Could you please clarify under which terms readers are allowed to use the example code in this repository?

TY!

Wrong culling of terrain (chapter 15)

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);

NullPointerException at Scanner constructor

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)

c21-p3: "Mesh" cannot be cast to "InstancedMesh"

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)

Typo in book.

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.

Unable to load resources

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.

Chapter 27 Part 1 crash

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.

Utils class loadResource method improvements

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.

Issue with Normal Mapping and Shadow Mapping

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.

http://prntscr.com/czcw5g

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

Branches

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.

Java 9 compatibility

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?

Chapter 7 question

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(?).

OSX issue with awt fonts?

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?

OBJ-Loader can't handle OBJ file with more Tex-Coordinates than vertices

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.

Resource Loader Method

In chapter 2, you have a Scanner allocated in memory, but never close it. Without closing it, memory will leak. I recommend this: PasteBin

Dependency is missing at chapter01

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 .

Error, i don't know whats happening, eclipse don't report any errors, i'm running the last episode code.

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)

New OpenGL features

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:

  • Direct State Access - from 4.5
  • Separated shaders with pipelines - from 4.1

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 :)

Question about spotlight reflection handling

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!

Terrain Issue

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());

Particles rendered at the camera position

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.

NullPointerException (chapter 7)

Hi, I am getting a NullPointerException but am not entirely sure why.

  • I have added the resources folder to the CLASSPATH.
  • I am using Eclipse Neon.
  • I can see that gameItems is null but still trying to figure out why this is.

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

java.lang.Exception: Could not find uniform:pointLights[0].color

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]

Typo in book and code

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.

Light Angle Renders Incorrectly When Object is Rotated

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.

ENHANCEMENT: Chapter Recommendations

As I have been reading through the book, I have a few ideas for future chapters that you can add (solely graphics).

  • Anti-Aliasing (SMAA, MSAA, FXAA, etc.)
  • Frustum Culling
  • Occlusion Culling
    I would also recommend looking back at your shaders. After you attach a shader to a program, you can delete it, as it will delete the plain-text version of the shader from the GPU, while leaving the compiled version active.

Distorted textures when using .obj from Blender

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

testblock_in_game

FATAL ERROR in native method error due to renderCrossHair

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

GLFW_VERSION_UNAVAILABLE error

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.

Error running example.

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)

Issues related with lights and memory leak

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:

  1. After starting application in memory creates two processes. But after closing window with game there is one process still lives.
  2. Point light doesn't work correctly. I use code source from 18.2 chapter and set only ambient and point lights. But only half of scene is under light.
  3. And why in Transformation class in method "updateGenericViewMatrix" - we don't rotate over Z position? If I set directional light in position(1,0,0) shadow will not be correctly displayed.
    light issue
    memory issue

Black Screen on normal Mapping

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:
image

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

FileSystemNotFoundException when launched from compiled jar

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.

Able to run CH28 with the RenderDoc but not with cmd.exe

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)

Minor render issue

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 running chapter 21 and 22

Error compiling Shader code: 0:167(2): error: return' with wrong type int, in functioncalcShadow' returning float

Solution:
In scene_fragment.fs, in calcShadow change return types from 1 to 1.0

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.