ginger3D is now my domain

master
hYdos 2020-02-22 09:08:28 +10:00
parent 038ea02cd6
commit 303cbb1993
47 changed files with 34 additions and 4786 deletions

View File

@ -83,6 +83,11 @@
<artifactId>soundsystem</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.github.hYdos</groupId>
<artifactId>Ginger3D</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>

View File

@ -4,22 +4,32 @@ import java.io.IOException;
import java.util.Random;
import org.aeonbits.owner.ConfigFactory;
import org.apache.commons.cli.*;
import org.apache.logging.log4j.*;
import org.joml.Vector3f;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.lwjgl.Version;
import org.lwjgl.glfw.*;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import com.github.halotroop.litecraft.input.*;
import com.github.halotroop.litecraft.input.Input;
import com.github.halotroop.litecraft.input.KeyCallbackHandler;
import com.github.halotroop.litecraft.input.Keybind;
import com.github.halotroop.litecraft.input.MouseCallbackHandler;
import com.github.halotroop.litecraft.logic.Timer;
import com.github.halotroop.litecraft.logic.Timer.TickListener;
import com.github.halotroop.litecraft.options.*;
import com.github.halotroop.litecraft.options.SettingsConfig;
import com.github.halotroop.litecraft.options.SettingsHandler;
import com.github.halotroop.litecraft.render.RenderWrapper;
import io.github.hydos.ginger.engine.elements.objects.RenderPlayer;
import io.github.hydos.ginger.engine.elements.objects.Player;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.mathEngine.vectors.Vector3f;
import io.github.hydos.ginger.engine.obj.ModelLoader;
import io.github.hydos.ginger.engine.render.models.TexturedModel;
import io.github.hydos.ginger.engine.renderEngine.models.TexturedModel;
public class LiteCraftMain implements Runnable
{
@ -94,7 +104,7 @@ public class LiteCraftMain implements Runnable
TexturedModel tModel = ModelLoader.loadModel("stall.obj", "stallTexture.png");
tModel.getTexture().setReflectivity(1f);
tModel.getTexture().setShineDamper(7f);
RenderPlayer renderPlayer = new RenderPlayer(tModel, new Vector3f(0, 0, -3), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f));
Player renderPlayer = new Player(tModel, new Vector3f(0, 0, -3), 0, 180f, 0, new Vector3f(0.2f, 0.2f, 0.2f));
RenderWrapper.init(splashText, renderPlayer);
long windowId = Window.window;
KeyCallbackHandler.trackWindow(windowId);

View File

@ -1,19 +1,22 @@
package com.github.halotroop.litecraft.render;
import java.util.*;
import org.joml.*;
import java.util.ArrayList;
import java.util.List;
import com.github.halotroop.litecraft.LiteCraftMain;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.GuiTexture;
import io.github.hydos.ginger.engine.elements.objects.*;
import io.github.hydos.ginger.engine.elements.objects.Entity;
import io.github.hydos.ginger.engine.elements.objects.Light;
import io.github.hydos.ginger.engine.elements.objects.Player;
import io.github.hydos.ginger.engine.font.TextMaster;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.mathEngine.vectors.Vector3f;
import io.github.hydos.ginger.engine.mathEngine.vectors.Vector4f;
import io.github.hydos.ginger.engine.particle.ParticleMaster;
import io.github.hydos.ginger.engine.postprocessing.PostProcessing;
import io.github.hydos.ginger.engine.render.MasterRenderer;
import io.github.hydos.ginger.engine.postProcessing.PostProcessing;
import io.github.hydos.ginger.engine.renderEngine.MasterRenderer;
import io.github.hydos.ginger.engine.terrain.Terrain;
import io.github.hydos.ginger.engine.utils.Loader;
import io.github.hydos.ginger.main.GingerMain;
@ -31,7 +34,7 @@ public class RenderWrapper
private static final List<Terrain> TERRAIN = new ArrayList<Terrain>();
private static final List<Entity> NORMAL_ENTITY = new ArrayList<Entity>();
public static void init(String splash, RenderPlayer renderPlayer)
public static void init(String splash, Player renderPlayer)
{
camera = new ThirdPersonCamera(new Vector3f(0, 0.1f, 0), renderPlayer);
Window.setBackgroundColour(96 / 256F, 26 / 256F, 108 / 25F);

View File

@ -1,22 +0,0 @@
package io.github.hydos.ginger.UI;
import java.util.List;
import io.github.hydos.ginger.UI.enums.*;
import io.github.hydos.ginger.engine.elements.GuiTexture;
public abstract class UICanvas
{
UIDefaultClipSide clippingSide = UIDefaultClipSide.centre;
UIType type = UIType.tab;
String tabName = "Welcome";
public UICanvas()
{}
public abstract void update();
public abstract void hide(List<GuiTexture> textures);
public abstract void show(List<GuiTexture> textures);
}

View File

@ -1,110 +0,0 @@
package io.github.hydos.ginger.engine.cameras;
import org.joml.Vector3f;
import org.lwjgl.glfw.*;
import io.github.hydos.ginger.engine.elements.objects.RenderPlayer;
import io.github.hydos.ginger.engine.io.Window;
public class ThirdPersonCamera
{
private float distanceFromPlayer = 5;
private float angleAroundPlayer = 0;
private Vector3f position = new Vector3f(0, 0, 0);
private float pitch, yaw;
private float roll;
private RenderPlayer player;
public ThirdPersonCamera(RenderPlayer player)
{ this.player = player; }
public ThirdPersonCamera(Vector3f vector3f, RenderPlayer player)
{
this.position = vector3f;
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 void invertPitch()
{ this.pitch = -pitch; }
public Vector3f getPosition()
{ return position; }
public float getPitch()
{ return pitch; }
public float getYaw()
{ return yaw; }
public float getRoll()
{ return roll; }
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;
}
private float calculateHorizontalDistance()
{
float hD = (float) (distanceFromPlayer * Math.cos(Math.toRadians(pitch)));
if (hD < 0)
hD = 0;
return hD;
}
private float calculateVerticalDistance()
{ return (float) (distanceFromPlayer * Math.sin(Math.toRadians(pitch + 4))); }
private void calculateZoom()
{
GLFW.glfwSetScrollCallback(Window.window, new GLFWScrollCallback()
{
@Override
public void invoke(long win, double dx, double dy)
{
float zoomLevel = (float) dy * 0.1f;
distanceFromPlayer -= zoomLevel;
}
});
}
private void calculatePitch()
{
if (Window.isMouseDown(1))
{
float pitchChange = (float) (Window.dy * 0.2f);
pitch += pitchChange;
if (pitch < 0)
{
pitch = 0;
}
else if (pitch > 90)
{ pitch = 90; }
}
}
private void calculateAngleAroundPlayer()
{
if (Window.isMouseDown(1))
{
float angleChange = (float) (Window.dx * 0.3f);
angleAroundPlayer -= angleChange;
}
}
}

View File

@ -1,160 +0,0 @@
package io.github.hydos.ginger.engine.font;
import org.joml.*;
/** Represents a piece of text in the game. */
public class GUIText
{
private String textString;
private float fontSize;
private int textMeshVao;
private int vertexCount;
private Vector3f colour = new Vector3f(0f, 0f, 0f), outlineColour;
private float borderEdge = 0.1f, borderWidth = 0;
private Vector2f offset = new Vector2f(0, 0);
private Vector2f position;
private float lineMaxSize;
private int numberOfLines;
private FontType font;
private boolean centerText = false;
/** Creates a new text, loads the text's quads into a VAO, and adds the text
* to the screen.
*
* @param text
* - the text.
* @param fontSize
* - the font size of the text, where a font size of 1 is the
* default size.
* @param font
* - the font that this text should use.
* @param position
* - the position on the screen where the top left corner of the
* text should be rendered. The top left corner of the screen is
* (0, 0) and the bottom right is (1, 1).
* @param maxLineLength
* - basically the width of the virtual page in terms of screen
* width (1 is full screen width, 0.5 is half the width of the
* screen, etc.) Text cannot go off the edge of the page, so if
* the text is longer than this length it will go onto the next
* line. When text is centered it is centered into the middle of
* the line, based on this line length value.
* @param centered
* - whether the text should be centered or not. */
public GUIText(String text, float fontSize, FontType font, Vector2f position, float maxLineLength,
boolean centered)
{
this.textString = text;
this.fontSize = fontSize;
this.font = font;
this.position = position;
this.outlineColour = colour;
this.lineMaxSize = maxLineLength;
this.centerText = centered;
TextMaster.loadText(this);
}
/** Remove the text from the screen. */
public void remove()
{ TextMaster.removeText(this); }
/** @return The font used by this text. */
public FontType getFont()
{ return font; }
/** Set the colour of the text.
*
* @param r
* - red value, between 0 and 1.
* @param g
* - green value, between 0 and 1.
* @param b
* - blue value, between 0 and 1. */
public void setColour(float r, float g, float b)
{ colour.set(r, g, b); }
/** @return the colour of the text. */
public Vector3f getColour()
{ return colour; }
/** @return The number of lines of text. This is determined when the text is
* loaded, based on the length of the text and the max line length
* that is set. */
public int getNumberOfLines()
{ return numberOfLines; }
/** @return The position of the top-left corner of the text in screen-space.
* (0, 0) is the top left corner of the screen, (1, 1) is the bottom
* right. */
public Vector2f getPosition()
{ return position; }
/** @return the ID of the text's VAO, which contains all the vertex data for
* the quads on which the text will be rendered. */
public int getMesh()
{ return textMeshVao; }
/** Set the VAO and vertex count for this text.
*
* @param vao
* - the VAO containing all the vertex data for the quads on
* which the text will be rendered.
* @param verticesCount
* - the total number of vertices in all of the quads. */
public void setMeshInfo(int vao, int verticesCount)
{
this.textMeshVao = vao;
this.vertexCount = verticesCount;
}
/** @return The total number of vertices of all the text's quads. */
public int getVertexCount()
{ return this.vertexCount; }
/** @return the font size of the text (a font size of 1 is normal). */
protected float getFontSize()
{ return fontSize; }
/** Sets the number of lines that this text covers (method used only in
* loading).
*
* @param number */
protected void setNumberOfLines(int number)
{ this.numberOfLines = number; }
/** @return {@code true} if the text should be centered. */
protected boolean isCentered()
{ return centerText; }
/** @return The maximum length of a line of this text. */
protected float getMaxLineSize()
{ return lineMaxSize; }
/** @return The string of text. */
protected String getTextString()
{ return textString; }
public Vector3f getOutlineColour()
{ return outlineColour; }
public float getBorderEdge()
{ return borderEdge; }
public void setBorderEdge(float borderEdge)
{ this.borderEdge = borderEdge; }
public float getBorderWidth()
{ return borderWidth; }
public void setBorderWidth(float borderWidth)
{ this.borderWidth = borderWidth; }
public Vector2f getOffset()
{ return offset; }
public void setOffset(Vector2f offset)
{ this.offset = offset; }
public void setOutlineColour(Vector3f outlineColour)
{ this.outlineColour = outlineColour; }
}

View File

@ -1,63 +0,0 @@
package io.github.hydos.ginger.engine.font;
import java.util.*;
/** Represents a line of text during the loading of a text.
*
* @author Karl */
public class Line
{
private double maxLength;
private double spaceSize;
private List<Word> words = new ArrayList<Word>();
private double currentLineLength = 0;
/** Creates an empty line.
*
* @param spaceWidth
* - the screen-space width of a space character.
* @param fontSize
* - the size of font being used.
* @param maxLength
* - the screen-space maximum length of a line. */
protected Line(double spaceWidth, double fontSize, double maxLength)
{
this.spaceSize = spaceWidth * fontSize;
this.maxLength = maxLength;
}
/** Attempt to add a word to the line. If the line can fit the word in
* without reaching the maximum line length then the word is added and the
* line length increased.
*
* @param word
* - the word to try to add.
* @return {@code true} if the word has successfully been added to the line. */
protected boolean attemptToAddWord(Word word)
{
double additionalLength = word.getWordWidth();
additionalLength += !words.isEmpty() ? spaceSize : 0;
if (currentLineLength + additionalLength <= maxLength)
{
words.add(word);
currentLineLength += additionalLength;
return true;
}
else
{
return false;
}
}
/** @return The max length of the line. */
protected double getMaxLength()
{ return maxLength; }
/** @return The current screen-space length of the line. */
protected double getLineLength()
{ return currentLineLength; }
/** @return The list of words in the line. */
protected List<Word> getWords()
{ return words; }
}

View File

@ -1,194 +0,0 @@
package io.github.hydos.ginger.engine.font;
import java.io.*;
import java.util.*;
import com.github.halotroop.litecraft.LiteCraftMain;
/** Provides functionality for getting the values from a font file. */
public class MetaFile
{
private static final int PAD_TOP = 0;
private static final int PAD_LEFT = 1;
private static final int PAD_BOTTOM = 2;
private static final int PAD_RIGHT = 3;
private static final int DESIRED_PADDING = 8;
private static final String SPLITTER = " ";
private static final String NUMBER_SEPARATOR = ",";
private double aspectRatio;
private double verticalPerPixelSize;
private double horizontalPerPixelSize;
private double spaceWidth;
private int[] padding;
private int paddingWidth;
private int paddingHeight;
private Map<Integer, Character> metaData = new HashMap<Integer, Character>();
private BufferedReader reader;
private Map<String, String> values = new HashMap<String, String>();
/** Opens a font file in preparation for reading.
*
* @param file
* - the font file. */
protected MetaFile(String file)
{
this.aspectRatio = (double) LiteCraftMain.width / (double) LiteCraftMain.height;
openFile(file);
loadPaddingData();
loadLineSizes();
int imageWidth = getValueOfVariable("scaleW");
loadCharacterData(imageWidth);
close();
}
protected double getSpaceWidth()
{ return spaceWidth; }
protected Character getCharacter(int ascii)
{ return metaData.get(ascii); }
/** Read in the next line and store the variable values.
*
* @return {@code true} if the end of the file hasn't been reached. */
private boolean processNextLine()
{
values.clear();
String line = null;
try
{
line = reader.readLine();
}
catch (IOException e1)
{
}
if (line == null)
{ return false; }
for (String part : line.split(SPLITTER))
{
String[] valuePairs = part.split("=");
if (valuePairs.length == 2)
{ values.put(valuePairs[0], valuePairs[1]); }
}
return true;
}
/** Gets the {@code int} value of the variable with a certain name on the
* current line.
*
* @param variable
* - the name of the variable.
* @return The value of the variable. */
private int getValueOfVariable(String variable)
{ return Integer.parseInt(values.get(variable)); }
/** Gets the array of ints associated with a variable on the current line.
*
* @param variable
* - the name of the variable.
* @return The int array of values associated with the variable. */
private int[] getValuesOfVariable(String variable)
{
String[] numbers = values.get(variable).split(NUMBER_SEPARATOR);
int[] actualValues = new int[numbers.length];
for (int i = 0; i < actualValues.length; i++)
{ actualValues[i] = Integer.parseInt(numbers[i]); }
return actualValues;
}
/** Closes the font file after finishing reading. */
private void close()
{
try
{
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/** Opens the font file, ready for reading.
*
* @param file
* - the font file. */
private void openFile(String file)
{
try
{
reader = new BufferedReader(new InputStreamReader(Class.class.getResourceAsStream("/fonts/" + file)));
}
catch (Exception e)
{
e.printStackTrace();
System.err.println("Couldn't read font meta file!");
}
}
/** Loads the data about how much padding is used around each character in
* the texture atlas. */
private void loadPaddingData()
{
processNextLine();
this.padding = getValuesOfVariable("padding");
this.paddingWidth = padding[PAD_LEFT] + padding[PAD_RIGHT];
this.paddingHeight = padding[PAD_TOP] + padding[PAD_BOTTOM];
}
/** Loads information about the line height for this font in pixels, and uses
* this as a way to find the conversion rate between pixels in the texture
* atlas and screen-space. */
private void loadLineSizes()
{
processNextLine();
int lineHeightPixels = getValueOfVariable("lineHeight") - paddingHeight;
verticalPerPixelSize = TextMeshCreator.LINE_HEIGHT / lineHeightPixels;
horizontalPerPixelSize = verticalPerPixelSize / aspectRatio;
}
/** Loads in data about each character and stores the data in the
* {@link Character} class.
*
* @param imageWidth
* - the width of the texture atlas in pixels. */
private void loadCharacterData(int imageWidth)
{
processNextLine();
processNextLine();
while (processNextLine())
{
Character c = loadCharacter(imageWidth);
if (c != null)
{ metaData.put(c.getId(), c); }
}
}
/** Loads all the data about one character in the texture atlas and converts
* it all from 'pixels' to 'screen-space' before storing. The effects of
* padding are also removed from the data.
*
* @param imageSize
* - the size of the texture atlas in pixels.
* @return The data about the character. */
private Character loadCharacter(int imageSize)
{
int id = getValueOfVariable("id");
if (id == TextMeshCreator.SPACE_ASCII)
{
this.spaceWidth = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
return null;
}
double xTex = ((double) getValueOfVariable("x") + (padding[PAD_LEFT] - DESIRED_PADDING)) / imageSize;
double yTex = ((double) getValueOfVariable("y") + (padding[PAD_TOP] - DESIRED_PADDING)) / imageSize;
int width = getValueOfVariable("width") - (paddingWidth - (2 * DESIRED_PADDING));
int height = getValueOfVariable("height") - ((paddingHeight) - (2 * DESIRED_PADDING));
double quadWidth = width * horizontalPerPixelSize;
double quadHeight = height * verticalPerPixelSize;
double xTexSize = (double) width / imageSize;
double yTexSize = (double) height / imageSize;
double xOff = (getValueOfVariable("xoffset") + padding[PAD_LEFT] - DESIRED_PADDING) * horizontalPerPixelSize;
double yOff = (getValueOfVariable("yoffset") + (padding[PAD_TOP] - DESIRED_PADDING)) * verticalPerPixelSize;
double xAdvance = (getValueOfVariable("xadvance") - paddingWidth) * horizontalPerPixelSize;
return new Character(id, xTex, yTex, xTexSize, yTexSize, xOff, yOff, quadWidth, quadHeight, xAdvance);
}
}

View File

@ -1,44 +0,0 @@
package io.github.hydos.ginger.engine.font;
import java.util.*;
import io.github.hydos.ginger.engine.render.renderers.FontRenderer;
import io.github.hydos.ginger.engine.utils.Loader;
public class TextMaster
{
private static Map<FontType, List<GUIText>> texts = new HashMap<FontType, List<GUIText>>();
private static FontRenderer renderer;
public static void init()
{ renderer = new FontRenderer(); }
public static void loadText(GUIText text)
{
FontType font = text.getFont();
TextMeshData data = font.loadText(text);
int vao = Loader.loadToVAO(data.getVertexPositions(), data.getTextureCoords());
text.setMeshInfo(vao, data.getVertexCount());
List<GUIText> textBatch = texts.get(font);
if (textBatch == null)
{
textBatch = new ArrayList<GUIText>();
texts.put(font, textBatch);
}
textBatch.add(text);
}
public static void removeText(GUIText text)
{
List<GUIText> textBatch = texts.get(text.getFont());
textBatch.remove(text);
if (textBatch.isEmpty())
{ texts.remove(text.getFont()); }
}
public static void cleanUp()
{ renderer.cleanUp(); }
public static void render()
{ renderer.render(texts); }
}

View File

@ -1,142 +0,0 @@
package io.github.hydos.ginger.engine.font;
import java.util.*;
public class TextMeshCreator
{
protected static final double LINE_HEIGHT = 0.03f;
protected static final int SPACE_ASCII = 32;
private MetaFile metaData;
protected TextMeshCreator(String metaFile)
{ metaData = new MetaFile(metaFile); }
protected TextMeshData createTextMesh(GUIText text)
{
List<Line> lines = createStructure(text);
TextMeshData data = createQuadVertices(text, lines);
return data;
}
private List<Line> createStructure(GUIText text)
{
char[] chars = text.getTextString().toCharArray();
List<Line> lines = new ArrayList<Line>();
Line currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
Word currentWord = new Word(text.getFontSize());
for (char c : chars)
{
int ascii = c;
if (ascii == SPACE_ASCII)
{
boolean added = currentLine.attemptToAddWord(currentWord);
if (!added)
{
lines.add(currentLine);
currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
currentLine.attemptToAddWord(currentWord);
}
currentWord = new Word(text.getFontSize());
continue;
}
Character character = metaData.getCharacter(ascii);
currentWord.addCharacter(character);
}
completeStructure(lines, currentLine, currentWord, text);
return lines;
}
private void completeStructure(List<Line> lines, Line currentLine, Word currentWord, GUIText text)
{
boolean added = currentLine.attemptToAddWord(currentWord);
if (!added)
{
lines.add(currentLine);
currentLine = new Line(metaData.getSpaceWidth(), text.getFontSize(), text.getMaxLineSize());
currentLine.attemptToAddWord(currentWord);
}
lines.add(currentLine);
}
private TextMeshData createQuadVertices(GUIText text, List<Line> lines)
{
text.setNumberOfLines(lines.size());
double curserX = 0f;
double curserY = 0f;
List<Float> vertices = new ArrayList<Float>();
List<Float> textureCoords = new ArrayList<Float>();
for (Line line : lines)
{
if (text.isCentered())
{ curserX = (line.getMaxLength() - line.getLineLength()) / 2; }
for (Word word : line.getWords())
{
for (Character letter : word.getCharacters())
{
addVerticesForCharacter(curserX, curserY, letter, text.getFontSize(), vertices);
addTexCoords(textureCoords, letter.getxTextureCoord(), letter.getyTextureCoord(),
letter.getXMaxTextureCoord(), letter.getYMaxTextureCoord());
curserX += letter.getxAdvance() * text.getFontSize();
}
curserX += metaData.getSpaceWidth() * text.getFontSize();
}
curserX = 0;
curserY += LINE_HEIGHT * text.getFontSize();
}
return new TextMeshData(listToArray(vertices), listToArray(textureCoords));
}
private void addVerticesForCharacter(double curserX, double curserY, Character character, double fontSize,
List<Float> vertices)
{
double x = curserX + (character.getxOffset() * fontSize);
double y = curserY + (character.getyOffset() * fontSize);
double maxX = x + (character.getSizeX() * fontSize);
double maxY = y + (character.getSizeY() * fontSize);
double properX = (2 * x) - 1;
double properY = (-2 * y) + 1;
double properMaxX = (2 * maxX) - 1;
double properMaxY = (-2 * maxY) + 1;
addVertices(vertices, properX, properY, properMaxX, properMaxY);
}
private static void addVertices(List<Float> vertices, double x, double y, double maxX, double maxY)
{
vertices.add((float) x);
vertices.add((float) y);
vertices.add((float) x);
vertices.add((float) maxY);
vertices.add((float) maxX);
vertices.add((float) maxY);
vertices.add((float) maxX);
vertices.add((float) maxY);
vertices.add((float) maxX);
vertices.add((float) y);
vertices.add((float) x);
vertices.add((float) y);
}
private static void addTexCoords(List<Float> texCoords, double x, double y, double maxX, double maxY)
{
texCoords.add((float) x);
texCoords.add((float) y);
texCoords.add((float) x);
texCoords.add((float) maxY);
texCoords.add((float) maxX);
texCoords.add((float) maxY);
texCoords.add((float) maxX);
texCoords.add((float) maxY);
texCoords.add((float) maxX);
texCoords.add((float) y);
texCoords.add((float) x);
texCoords.add((float) y);
}
private static float[] listToArray(List<Float> listOfFloats)
{
float[] array = new float[listOfFloats.size()];
for (int i = 0; i < array.length; i++)
{ array[i] = listOfFloats.get(i); }
return array;
}
}

View File

@ -1,34 +0,0 @@
package io.github.hydos.ginger.engine.font;
import java.util.*;
/** During the loading of a text this represents one word in the text. */
public class Word
{
private List<Character> characters = new ArrayList<Character>();
private double width = 0;
private double fontSize;
/** Create a new empty word.
*
* @param fontSize - the font size of the text which this word is in. */
protected Word(double fontSize)
{ this.fontSize = fontSize; }
/** Adds a character to the end of the current word and increases the screen-space width of the word.
*
* @param character - the character to be added. */
protected void addCharacter(Character character)
{
characters.add(character);
width += character.getxAdvance() * fontSize;
}
/** @return The list of characters in the word. */
protected List<Character> getCharacters()
{ return characters; }
/** @return The width of the word in terms of screen size. */
protected double getWordWidth()
{ return width; }
}

View File

@ -1,190 +0,0 @@
package io.github.hydos.ginger.engine.io;
import java.nio.*;
import org.joml.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.*;
import com.github.halotroop.litecraft.LiteCraftMain;
import io.github.hydos.ginger.engine.render.texture.Image;
public class Window
{
private static String title;
public static long window;
private static Vector3f backgroundColour = new Vector3f(0.2f, 0.2f, 0.6f);
private static boolean[] keys = new boolean[GLFW.GLFW_KEY_LAST];
private static boolean[] mouseButtons = new boolean[GLFW.GLFW_MOUSE_BUTTON_LAST];
private static GLFWImage.Buffer iconBuffer = null;
private static double fpsCap, time, processedTime = 0;
public static double dy = 0;
public static double dx = 0;
static double oldX = 0;
static double oldY = 0;
static double newX = 0;
static double newY = 0;
public static GLCapabilities glContext;
public static int actuallWidth, actuallHeight;
public static void create(int width, int height, String title, int fps)
{
Window.actuallHeight = height;
Window.actuallWidth = width;
Window.title = title;
fpsCap = fps;
create();
}
public static void create()
{
if (!GLFW.glfwInit())
{
System.err.println("Error: Couldn't initialize GLFW");
System.exit(-1);
}
GLFW.glfwWindowHint(GLFW.GLFW_VISIBLE, GLFW.GLFW_FALSE);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MAJOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 3);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GL11.GL_TRUE);
GLFW.glfwWindowHint(GLFW.GLFW_RESIZABLE, GLFW.GLFW_TRUE);
GLFWVidMode vidmode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
window = GLFW.glfwCreateWindow(actuallWidth, actuallHeight, title, (LiteCraftMain.fullscreen) ? GLFW.glfwGetPrimaryMonitor() : 0, window);
if (window == 0)
{
System.err.println("Error: Couldnt initilize window");
System.exit(-1);
}
GLFW.glfwMakeContextCurrent(window);
glContext = GL.createCapabilities();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GLFW.glfwSetWindowPos(window, (vidmode.width() - LiteCraftMain.width) / 2, (vidmode.height() - LiteCraftMain.height) / 2);
GLFW.glfwShowWindow(window);
time = getTime();
getCurrentTime();
}
public static boolean closed()
{ return GLFW.glfwWindowShouldClose(window); }
public static void update()
{
IntBuffer widthBuffer = BufferUtils.createIntBuffer(1);
IntBuffer heightBuffer = BufferUtils.createIntBuffer(1);
GLFW.glfwGetWindowSize(window, widthBuffer, heightBuffer);
GL11.glViewport(0, 0, LiteCraftMain.width, LiteCraftMain.height);
GL11.glClearColor(backgroundColour.x, backgroundColour.y, backgroundColour.z, 1.0f);
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GLFW.glfwPollEvents();
newX = Window.getMouseX();
newY = Window.getMouseY();
Window.dx = newX - oldX;
Window.dy = newY - oldY;
oldX = newX;
oldY = newY;
}
public static void swapBuffers()
{ GLFW.glfwSwapBuffers(window); }
public static boolean isKeyDown(int keycode)
{ return GLFW.glfwGetKey(window, keycode) == 1; }
public static boolean isMouseDown(int mouseButton)
{ return GLFW.glfwGetMouseButton(window, mouseButton) == 1; }
public static boolean isKeyPressed(int keyCode)
{ return isKeyDown(keyCode) && !keys[keyCode]; }
public static boolean isKeyReleased(int keyCode)
{ return !isKeyDown(keyCode) && keys[keyCode]; }
public static boolean isMousePressed(int keyCode)
{ return isMouseDown(keyCode) && !mouseButtons[keyCode]; }
public static boolean isMouseReleased(int keyCode)
{ return !isMouseDown(keyCode) && mouseButtons[keyCode]; }
public static double getMouseX()
{
DoubleBuffer buffer = BufferUtils.createDoubleBuffer(1);
GLFW.glfwGetCursorPos(window, buffer, null);
return buffer.get(0);
}
public static double getMouseY()
{
DoubleBuffer buffer = BufferUtils.createDoubleBuffer(1);
GLFW.glfwGetCursorPos(window, null, buffer);
return buffer.get(0);
}
public static double getTime()
{
double f = (double) System.nanoTime() / (double) 1000000000;
return f;
}
public static float getFloatTime()
{
float f = (System.nanoTime() / (float) 1000000000);
return f;
}
public static boolean isUpdating()
{
double nextTime = getTime();
double passedTime = nextTime - time;
processedTime += passedTime;
time = nextTime;
while (processedTime > 1.0 / fpsCap)
{
processedTime -= 1.0 / fpsCap;
return true;
}
return false;
}
public static void stop()
{ GLFW.glfwTerminate(); }
public static void setBackgroundColour(float r, float g, float b)
{ backgroundColour = new Vector3f(r, g, b); }
public static void setIcon(String path)
{
Image icon = Image.createImage("/res/textures/" + path);
GLFWImage iconImage = GLFWImage.malloc();
iconBuffer = GLFWImage.malloc(1);
iconImage.set(icon.getWidth(), icon.getHeight(), icon.getImage());
iconBuffer.put(0, iconImage);
}
public static void showIcon()
{
if (iconBuffer != null)
{ GLFW.glfwSetWindowIcon(window, iconBuffer); }
}
public static void lockMouse()
{ GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); }
public static void unlockMouse()
{ GLFW.glfwSetInputMode(window, GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); }
public static Vector3f getColour()
{ return Window.backgroundColour; }
private static long getCurrentTime()
{ return (long) (GLFW.glfwGetTime() * 1000 / GLFW.glfwGetTimerFrequency()); }
public static Vector2f getNormalizedMouseCoordinates()
{
float normalX = -1.0f + 2.0f * (float) getMouseX() / LiteCraftMain.width;
float normalY = 1.0f - 2.0f * (float) getMouseY() / LiteCraftMain.height;
return new Vector2f(normalX, normalY);
}
}

View File

@ -1,82 +0,0 @@
package io.github.hydos.ginger.engine.math;
import java.lang.Math;
import org.joml.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
public class Maths
{
public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry, float rz, Vector3f scale)
{
Matrix4f matrix = new Matrix4f();
matrix.identity();
matrix.translate(translation, matrix);
matrix.rotate((float) Math.toRadians(rx), new Vector3f(1, 0, 0), matrix);
matrix.rotate((float) Math.toRadians(ry), new Vector3f(0, 1, 0), matrix);
matrix.rotate((float) Math.toRadians(rz), new Vector3f(0, 0, 1), matrix);
matrix.scale(scale, matrix);
return matrix;
}
public static Matrix4f createViewMatrix(ThirdPersonCamera camera)
{
Matrix4f viewMatrix = new Matrix4f();
viewMatrix.identity();
viewMatrix.rotate((float) Math.toRadians(camera.getPitch()), new Vector3f(1, 0, 0), viewMatrix);
viewMatrix.rotate((float) Math.toRadians(camera.getYaw()), new Vector3f(0, 1, 0), viewMatrix);
viewMatrix.rotate((float) Math.toRadians(camera.getRoll()), new Vector3f(0, 0, 1), viewMatrix);
Vector3f cameraPos = camera.getPosition();
Vector3f negativeCameraPos = new Vector3f(-cameraPos.x, -cameraPos.y, -cameraPos.z);
viewMatrix.translate(negativeCameraPos, viewMatrix);
return viewMatrix;
}
public static float barryCentric(Vector3f p1, Vector3f p2, Vector3f p3, Vector2f pos)
{
float det = (p2.z - p3.z) * (p1.x - p3.x) + (p3.x - p2.x) * (p1.z - p3.z);
float l1 = ((p2.z - p3.z) * (pos.x - p3.x) + (p3.x - p2.x) * (pos.y - p3.z)) / det;
float l2 = ((p3.z - p1.z) * (pos.x - p3.x) + (p1.x - p3.x) * (pos.y - p3.z)) / det;
float l3 = 1.0f - l1 - l2;
return l1 * p1.y + l2 * p2.y + l3 * p3.y;
}
public static Matrix4f createTransformationMatrix(Vector2f translation, Vector2f scale)
{
Matrix4f matrix = new Matrix4f();
matrix.identity();
matrix.translate(new Vector3f(translation.x, translation.y, 1), matrix);
matrix.scale(new Vector3f(scale.x, scale.y, 1f), matrix);
return matrix;
}
public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry, float rz, float scale)
{
Matrix4f matrix = new Matrix4f();
matrix.identity();
matrix.translate(translation, matrix);
matrix.rotate((float) Math.toRadians(rx), new Vector3f(1, 0, 0), matrix);
matrix.rotate((float) Math.toRadians(ry), new Vector3f(0, 1, 0), matrix);
matrix.rotate((float) Math.toRadians(rz), new Vector3f(0, 0, 1), matrix);
Vector3f newScale = new Vector3f(scale, scale, scale);
matrix.scale(newScale, matrix);
return matrix;
}
public static Vector3f Vec4ToVec3(Vector4f eyeSpacePos)
{
Vector3f vec3 = new Vector3f();
vec3.x = eyeSpacePos.x;
vec3.y = eyeSpacePos.y;
vec3.z = eyeSpacePos.z;
return vec3;
}
public static void scale(Vector3f change, float time)
{
change.x = change.x * time;
change.y = change.y * time;
change.x = change.x * time;
}
}

View File

@ -1,173 +0,0 @@
package io.github.hydos.ginger.engine.obj;
import java.io.*;
import java.util.*;
import org.joml.*;
public class OBJFileLoader
{
private static final String RES_LOC = "/models/";
public static ModelData loadOBJ(String objFileName)
{
String objFile = RES_LOC + objFileName;
InputStreamReader isr = new InputStreamReader(OBJFileLoader.class.getResourceAsStream(objFile));
BufferedReader reader = new BufferedReader(isr);
String line;
List<Vertex> vertices = new ArrayList<Vertex>();
List<Vector2f> textures = new ArrayList<Vector2f>();
List<Vector3f> normals = new ArrayList<Vector3f>();
List<Integer> indices = new ArrayList<Integer>();
try
{
while (true)
{
line = reader.readLine();
if (line.startsWith("v "))
{
String[] currentLine = line.split(" ");
Vector3f vertex = new Vector3f(Float.valueOf(currentLine[1]),
Float.valueOf(currentLine[2]),
Float.valueOf(currentLine[3]));
Vertex newVertex = new Vertex(vertices.size(), vertex);
vertices.add(newVertex);
}
else if (line.startsWith("vt "))
{
String[] currentLine = line.split(" ");
Vector2f texture = new Vector2f(Float.valueOf(currentLine[1]),
Float.valueOf(currentLine[2]));
textures.add(texture);
}
else if (line.startsWith("vn "))
{
String[] currentLine = line.split(" ");
Vector3f normal = new Vector3f(Float.valueOf(currentLine[1]),
Float.valueOf(currentLine[2]),
Float.valueOf(currentLine[3]));
normals.add(normal);
}
else if (line.startsWith("f "))
{ break; }
}
while (line != null && line.startsWith("f "))
{
String[] currentLine = line.split(" ");
String[] vertex1 = currentLine[1].split("/");
String[] vertex2 = currentLine[2].split("/");
String[] vertex3 = currentLine[3].split("/");
processVertex(vertex1, vertices, indices);
processVertex(vertex2, vertices, indices);
processVertex(vertex3, vertices, indices);
line = reader.readLine();
}
reader.close();
}
catch (IOException e)
{
System.err.println("Error reading the file");
}
removeUnusedVertices(vertices);
float[] verticesArray = new float[vertices.size() * 3];
float[] texturesArray = new float[vertices.size() * 2];
float[] normalsArray = new float[vertices.size() * 3];
float furthest = convertDataToArrays(vertices, textures, normals, verticesArray,
texturesArray, normalsArray);
int[] indicesArray = convertIndicesListToArray(indices);
ModelData data = new ModelData(verticesArray, texturesArray, normalsArray, indicesArray,
furthest);
return data;
}
private static void processVertex(String[] vertex, List<Vertex> vertices, List<Integer> indices)
{
int index = Integer.parseInt(vertex[0]) - 1;
Vertex currentVertex = vertices.get(index);
int textureIndex = Integer.parseInt(vertex[1]) - 1;
int normalIndex = Integer.parseInt(vertex[2]) - 1;
if (!currentVertex.isSet())
{
currentVertex.setTextureIndex(textureIndex);
currentVertex.setNormalIndex(normalIndex);
indices.add(index);
}
else
{
dealWithAlreadyProcessedVertex(currentVertex, textureIndex, normalIndex, indices,
vertices);
}
}
private static int[] convertIndicesListToArray(List<Integer> indices)
{
int[] indicesArray = new int[indices.size()];
for (int i = 0; i < indicesArray.length; i++)
{ indicesArray[i] = indices.get(i); }
return indicesArray;
}
private static float convertDataToArrays(List<Vertex> vertices, List<Vector2f> textures,
List<Vector3f> normals, float[] verticesArray, float[] texturesArray,
float[] normalsArray)
{
float furthestPoint = 0;
for (int i = 0; i < vertices.size(); i++)
{
Vertex currentVertex = vertices.get(i);
if (currentVertex.getLength() > furthestPoint)
{ furthestPoint = currentVertex.getLength(); }
Vector3f position = currentVertex.getPosition();
Vector2f textureCoord = textures.get(currentVertex.getTextureIndex());
Vector3f normalVector = normals.get(currentVertex.getNormalIndex());
verticesArray[i * 3] = position.x;
verticesArray[i * 3 + 1] = position.y;
verticesArray[i * 3 + 2] = position.z;
texturesArray[i * 2] = textureCoord.x;
texturesArray[i * 2 + 1] = 1 - textureCoord.y;
normalsArray[i * 3] = normalVector.x;
normalsArray[i * 3 + 1] = normalVector.y;
normalsArray[i * 3 + 2] = normalVector.z;
}
return furthestPoint;
}
private static void dealWithAlreadyProcessedVertex(Vertex previousVertex, int newTextureIndex,
int newNormalIndex, List<Integer> indices, List<Vertex> vertices)
{
if (previousVertex.hasSameTextureAndNormal(newTextureIndex, newNormalIndex))
{
indices.add(previousVertex.getIndex());
}
else
{
Vertex anotherVertex = previousVertex.getDuplicateVertex();
if (anotherVertex != null)
{
dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex, newNormalIndex,
indices, vertices);
}
else
{
Vertex duplicateVertex = new Vertex(vertices.size(), previousVertex.getPosition());
duplicateVertex.setTextureIndex(newTextureIndex);
duplicateVertex.setNormalIndex(newNormalIndex);
previousVertex.setDuplicateVertex(duplicateVertex);
vertices.add(duplicateVertex);
indices.add(duplicateVertex.getIndex());
}
}
}
private static void removeUnusedVertices(List<Vertex> vertices)
{
for (Vertex vertex : vertices)
{
if (!vertex.isSet())
{
vertex.setTextureIndex(0);
vertex.setNormalIndex(0);
}
}
}
}

View File

@ -1,204 +0,0 @@
package io.github.hydos.ginger.engine.obj.normals;
import java.util.List;
import org.joml.*;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.models.RawModel;
@SuppressWarnings("unused")
public class NormalMappedObjLoader
{
public static RawModel loadOBJ(String objFileName)
{
// BufferedReader isr = null;
// isr = new BufferedReader(new InputStreamReader(Class.class.getResourceAsStream("/models/" + objFileName)));
// BufferedReader reader = new BufferedReader(isr);
// String line;
// List<VertexNM> vertices = new ArrayList<VertexNM>();
// List<Vector2f> textures = new ArrayList<Vector2f>();
// List<Vector3f> normals = new ArrayList<Vector3f>();
// List<Integer> indices = new ArrayList<Integer>();
// try
// {
// while (true)
// {
// line = reader.readLine();
// if (line.startsWith("v "))
// {
// String[] currentLine = line.split(" ");
// Vector3f vertex = new Vector3f(Float.valueOf(currentLine[1]),
// Float.valueOf(currentLine[2]),
// Float.valueOf(currentLine[3]));
// VertexNM newVertex = new VertexNM(vertices.size(), vertex);
// vertices.add(newVertex);
// }
// else if (line.startsWith("vt "))
// {
// String[] currentLine = line.split(" ");
// Vector2f texture = new Vector2f(Float.valueOf(currentLine[1]),
// Float.valueOf(currentLine[2]));
// textures.add(texture);
// }
// else if (line.startsWith("vn "))
// {
// String[] currentLine = line.split(" ");
// Vector3f normal = new Vector3f(Float.valueOf(currentLine[1]),
// Float.valueOf(currentLine[2]),
// Float.valueOf(currentLine[3]));
// normals.add(normal);
// }
// else if (line.startsWith("f "))
// { break; }
// }
// while (line != null && line.startsWith("f "))
// {
// String[] currentLine = line.split(" ");
// String[] vertex1 = currentLine[1].split("/");
// String[] vertex2 = currentLine[2].split("/");
// String[] vertex3 = currentLine[3].split("/");
// VertexNM v0 = processVertex(vertex1, vertices, indices);
// VertexNM v1 = processVertex(vertex2, vertices, indices);
// VertexNM v2 = processVertex(vertex3, vertices, indices);
// calculateTangents(v0, v1, v2, textures);//NEW
// line = reader.readLine();
// }
// reader.close();
// }
// catch (IOException e)
// {
// System.err.println("Error reading the file");
// }
// removeUnusedVertices(vertices);
// float[] verticesArray = new float[vertices.size() * 3];
// float[] texturesArray = new float[vertices.size() * 2];
// float[] normalsArray = new float[vertices.size() * 3];
// float[] tangentsArray = new float[vertices.size() * 3];
// @SuppressWarnings("unused")
// //some weird eclipse only error here i think
// float furthest = convertDataToArrays(vertices, textures, normals, verticesArray,
// texturesArray, normalsArray, tangentsArray);
// int[] indicesArray = convertIndicesListToArray(indices);
// return Loader.loadToVAO(verticesArray, indicesArray, normalsArray, tangentsArray, texturesArray);
return null;
}
private static void calculateTangents(VertexNM v0, VertexNM v1, VertexNM v2, List<Vector2f> textures)
{
Vector3f delatPos1 = new Vector3f().sub(v1.getPosition(), v0.getPosition());
Vector3f delatPos2 = new Vector3f().sub(v2.getPosition(), v0.getPosition());
Vector2f uv0 = textures.get(v0.getTextureIndex());
Vector2f uv1 = textures.get(v1.getTextureIndex());
Vector2f uv2 = textures.get(v2.getTextureIndex());
Vector2f deltaUv1 = new Vector2f().sub(uv1, uv0);
Vector2f deltaUv2 = new Vector2f().sub(uv2, uv0);
float r = 1.0f / (deltaUv1.x * deltaUv2.y - deltaUv1.y * deltaUv2.x);
Maths.scale(delatPos1, deltaUv2.y);
Maths.scale(delatPos2, deltaUv1.y);
Vector3f tangent = new Vector3f().sub(delatPos1, delatPos2);
Maths.scale(tangent, r);
v0.addTangent(tangent);
v1.addTangent(tangent);
v2.addTangent(tangent);
}
private static VertexNM processVertex(String[] vertex, List<VertexNM> vertices, List<Integer> indices)
{
int index = Integer.parseInt(vertex[0]) - 1;
VertexNM currentVertex = vertices.get(index);
int textureIndex = Integer.parseInt(vertex[1]) - 1;
int normalIndex = Integer.parseInt(vertex[2]) - 1;
if (!currentVertex.isSet())
{
currentVertex.setTextureIndex(textureIndex);
currentVertex.setNormalIndex(normalIndex);
indices.add(index);
return currentVertex;
}
else
{
return dealWithAlreadyProcessedVertex(currentVertex, textureIndex, normalIndex, indices,
vertices);
}
}
private static int[] convertIndicesListToArray(List<Integer> indices)
{
int[] indicesArray = new int[indices.size()];
for (int i = 0; i < indicesArray.length; i++)
{ indicesArray[i] = indices.get(i); }
return indicesArray;
}
private static float convertDataToArrays(List<VertexNM> vertices, List<Vector2f> textures,
List<Vector3f> normals, float[] verticesArray, float[] texturesArray,
float[] normalsArray, float[] tangentsArray)
{
float furthestPoint = 0;
for (int i = 0; i < vertices.size(); i++)
{
VertexNM currentVertex = vertices.get(i);
if (currentVertex.getLength() > furthestPoint)
{ furthestPoint = currentVertex.getLength(); }
Vector3f position = currentVertex.getPosition();
Vector2f textureCoord = textures.get(currentVertex.getTextureIndex());
Vector3f normalVector = normals.get(currentVertex.getNormalIndex());
Vector3f tangent = currentVertex.getAverageTangent();
verticesArray[i * 3] = position.x;
verticesArray[i * 3 + 1] = position.y;
verticesArray[i * 3 + 2] = position.z;
texturesArray[i * 2] = textureCoord.x;
texturesArray[i * 2 + 1] = 1 - textureCoord.y;
normalsArray[i * 3] = normalVector.x;
normalsArray[i * 3 + 1] = normalVector.y;
normalsArray[i * 3 + 2] = normalVector.z;
tangentsArray[i * 3] = tangent.x;
tangentsArray[i * 3 + 1] = tangent.y;
tangentsArray[i * 3 + 2] = tangent.z;
}
return furthestPoint;
}
private static VertexNM dealWithAlreadyProcessedVertex(VertexNM previousVertex, int newTextureIndex,
int newNormalIndex, List<Integer> indices, List<VertexNM> vertices)
{
if (previousVertex.hasSameTextureAndNormal(newTextureIndex, newNormalIndex))
{
indices.add(previousVertex.getIndex());
return previousVertex;
}
else
{
VertexNM anotherVertex = previousVertex.getDuplicateVertex();
if (anotherVertex != null)
{
return dealWithAlreadyProcessedVertex(anotherVertex, newTextureIndex,
newNormalIndex, indices, vertices);
}
else
{
VertexNM duplicateVertex = previousVertex.duplicate(vertices.size());
duplicateVertex.setTextureIndex(newTextureIndex);
duplicateVertex.setNormalIndex(newNormalIndex);
previousVertex.setDuplicateVertex(duplicateVertex);
vertices.add(duplicateVertex);
indices.add(duplicateVertex.getIndex());
return duplicateVertex;
}
}
}
private static void removeUnusedVertices(List<VertexNM> vertices)
{
for (VertexNM vertex : vertices)
{
vertex.averageTangents();
if (!vertex.isSet())
{
vertex.setTextureIndex(0);
vertex.setNormalIndex(0);
}
}
}
}

View File

@ -1,81 +0,0 @@
package io.github.hydos.ginger.engine.obj.normals;
import java.util.*;
import org.joml.Vector3f;
public class VertexNM
{
private static final int NO_INDEX = -1;
private Vector3f position;
private int textureIndex = NO_INDEX;
private int normalIndex = NO_INDEX;
private VertexNM duplicateVertex = null;
private int index;
private float length;
private List<Vector3f> tangents = new ArrayList<Vector3f>();
private Vector3f averagedTangent = new Vector3f(0, 0, 0);
protected VertexNM(int index, Vector3f position)
{
this.index = index;
this.position = position;
this.length = position.length();
}
protected void addTangent(Vector3f tangent)
{ tangents.add(tangent); }
//NEW
protected VertexNM duplicate(int newIndex)
{
VertexNM vertex = new VertexNM(newIndex, position);
vertex.tangents = this.tangents;
return vertex;
}
protected void averageTangents()
{
if (tangents.isEmpty())
{ return; }
for (Vector3f tangent : tangents)
{ averagedTangent.add(averagedTangent, tangent); }
averagedTangent.normalize();
}
protected Vector3f getAverageTangent()
{ return averagedTangent; }
protected int getIndex()
{ return index; }
protected float getLength()
{ return length; }
protected boolean isSet()
{ return textureIndex != NO_INDEX && normalIndex != NO_INDEX; }
protected boolean hasSameTextureAndNormal(int textureIndexOther, int normalIndexOther)
{ return textureIndexOther == textureIndex && normalIndexOther == normalIndex; }
protected void setTextureIndex(int textureIndex)
{ this.textureIndex = textureIndex; }
protected void setNormalIndex(int normalIndex)
{ this.normalIndex = normalIndex; }
protected Vector3f getPosition()
{ return position; }
protected int getTextureIndex()
{ return textureIndex; }
protected int getNormalIndex()
{ return normalIndex; }
protected VertexNM getDuplicateVertex()
{ return duplicateVertex; }
protected void setDuplicateVertex(VertexNM duplicateVertex)
{ this.duplicateVertex = duplicateVertex; }
}

View File

@ -1,97 +0,0 @@
package io.github.hydos.ginger.engine.particle;
import java.lang.Math;
import org.joml.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.main.settings.Constants;
public class Particle
{
private Vector3f position;
private Vector3f velocity;
private float gravityEffect;
private float lifeLength;
private float rotation;
private Vector3f scale;
private Vector2f texOffset1 = new Vector2f();
private Vector2f texOffset2 = new Vector2f();
private float blend;
private ParticleTexture texture;
private float elapsedTime = 0;
private float distance;
public Particle(ParticleTexture texture, Vector3f position, Vector3f velocity, float gravityEffect, float lifeLength, float rotation,
Vector3f scale)
{
super();
this.position = position;
this.velocity = velocity;
this.gravityEffect = gravityEffect;
this.lifeLength = lifeLength;
this.rotation = rotation;
this.scale = scale;
this.texture = texture;
ParticleMaster.addParticle(this);
}
public ParticleTexture getTexture()
{ return texture; }
public Vector3f getPosition()
{ return position; }
public float getDistance()
{ return distance; }
public float getRotation()
{ return rotation; }
public Vector3f getScale()
{ return scale; }
public Vector2f getTexOffset1()
{ return texOffset1; }
public Vector2f getTexOffset2()
{ return texOffset2; }
public float getBlend()
{ return blend; }
public boolean update(ThirdPersonCamera camera)
{
float time = (float) Window.getTime() / 1000000;
velocity.y += Constants.gravity * gravityEffect * time;
Vector3f change = new Vector3f(velocity);
Maths.scale(change, time);
position.add(change, position);
distance = position.sub(camera.getPosition(), position).lengthSquared();
elapsedTime += time;
updateTextureCoordInfo();
return elapsedTime < lifeLength;
}
private void updateTextureCoordInfo()
{
float lifeFactor = elapsedTime / lifeLength;
int stageCount = texture.getNumberOfRows() * texture.getNumberOfRows();
float atlasProgression = lifeFactor * stageCount;
int index1 = (int) Math.floor(atlasProgression);
int index2 = index1 < stageCount - 1 ? index1 + 1 : index1;
this.blend = atlasProgression % 1;
setTextureOffset(texOffset1, index1);
setTextureOffset(texOffset2, index2);
}
private void setTextureOffset(Vector2f offset, int index)
{
int column = index % texture.getNumberOfRows();
int row = index / texture.getNumberOfRows();
offset.x = (float) column / texture.getNumberOfRows();
offset.y = (float) row / texture.getNumberOfRows();
}
}

View File

@ -1,57 +0,0 @@
package io.github.hydos.ginger.engine.particle;
import java.util.*;
import java.util.Map.Entry;
import org.joml.Matrix4f;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.render.renderers.ParticleRenderer;
public class ParticleMaster
{
private static Map<ParticleTexture, List<Particle>> particles = new HashMap<ParticleTexture, List<Particle>>();
private static ParticleRenderer particleRenderer;
public static void init(Matrix4f projectionMatrix)
{ particleRenderer = new ParticleRenderer(projectionMatrix); }
public static void update(ThirdPersonCamera camera)
{
Iterator<Entry<ParticleTexture, List<Particle>>> mapIterator = particles.entrySet().iterator();
while (mapIterator.hasNext())
{
List<Particle> list = mapIterator.next().getValue();
Iterator<Particle> iterator = list.iterator();
while (iterator.hasNext())
{
Particle p = iterator.next();
boolean stillAlive = p.update(camera);
if (!stillAlive)
{
iterator.remove();
if (list.isEmpty())
{ mapIterator.remove(); }
}
}
InsertionSort.sortHighToLow(list);
}
}
public static void renderParticles(ThirdPersonCamera camera)
{ particleRenderer.render(particles, camera); }
public static void cleanUp()
{ particleRenderer.cleanUp(); }
public static void addParticle(Particle particle)
{
List<Particle> list = particles.get(particle.getTexture());
if (list == null)
{
list = new ArrayList<Particle>();
particles.put(particle.getTexture(), list);
}
list.add(particle);
}
}

View File

@ -1,138 +0,0 @@
package io.github.hydos.ginger.engine.particle;
import java.lang.Math;
import java.util.Random;
import org.joml.*;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.math.Maths;
public class ParticleSystem
{
private float pps, averageSpeed, gravityComplient, averageLifeLength, averageScale;
private float speedError, lifeError, scaleError = 0;
private boolean randomRotation = false;
private Vector3f direction;
private float directionDeviation = 0;
private ParticleTexture texture;
private Random random = new Random();
public ParticleSystem(ParticleTexture texture, float pps, float speed, float gravityComplient, float lifeLength, float scale)
{
this.pps = pps / 100000;
this.averageSpeed = speed;
this.gravityComplient = gravityComplient;
this.averageLifeLength = lifeLength;
this.averageScale = scale;
this.texture = texture;
}
/** @param direction - The average direction in which particles are emitted.
* @param deviation - A value between 0 and 1 indicating how far from the chosen direction particles can deviate. */
public void setDirection(Vector3f direction, float deviation)
{
this.direction = new Vector3f(direction);
this.directionDeviation = (float) (deviation * Math.PI);
}
public void randomizeRotation()
{ randomRotation = true; }
/** @param error
* - A number between 0 and 1, where 0 means no error margin. */
public void setSpeedError(float error)
{ this.speedError = error * averageSpeed; }
/** @param error
* - A number between 0 and 1, where 0 means no error margin. */
public void setLifeError(float error)
{ this.lifeError = error * averageLifeLength; }
/** @param error
* - A number between 0 and 1, where 0 means no error margin. */
public void setScaleError(float error)
{ this.scaleError = error * averageScale; }
public void generateParticles(Vector3f systemCenter)
{
float delta = (float) Window.getTime();
float particlesToCreate = pps * delta;
int count = (int) Math.floor(particlesToCreate);
float partialParticle = particlesToCreate % 1;
for (int i = 0; i < count; i++)
{ emitParticle(systemCenter); }
if (Math.random() < partialParticle)
{ emitParticle(systemCenter); }
}
private void emitParticle(Vector3f center)
{
Vector3f velocity = null;
if (direction != null)
{
velocity = generateRandomUnitVectorWithinCone(direction, directionDeviation);
}
else
{
velocity = generateRandomUnitVector();
}
velocity.normalize();
Maths.scale(velocity, generateValue(averageSpeed, speedError));
float scale = generateValue(averageScale, scaleError);
float lifeLength = generateValue(averageLifeLength, lifeError);
new Particle(texture, new Vector3f(center), velocity, gravityComplient, lifeLength, generateRotation(), new Vector3f(scale, scale, scale));
}
private float generateValue(float average, float errorMargin)
{
float offset = (random.nextFloat() - 0.5f) * 2f * errorMargin;
return average + offset;
}
private float generateRotation()
{
if (randomRotation)
{
return random.nextFloat() * 360f;
}
else
{
return 0;
}
}
private static Vector3f generateRandomUnitVectorWithinCone(Vector3f coneDirection, float angle)
{
float cosAngle = (float) Math.cos(angle);
Random random = new Random();
float theta = (float) (random.nextFloat() * 2f * Math.PI);
float z = cosAngle + (random.nextFloat() * (1 - cosAngle));
float rootOneMinusZSquared = (float) Math.sqrt(1 - z * z);
float x = (float) (rootOneMinusZSquared * Math.cos(theta));
float y = (float) (rootOneMinusZSquared * Math.sin(theta));
Vector4f direction = new Vector4f(x, y, z, 1);
if (coneDirection.x != 0 || coneDirection.y != 0 || (coneDirection.z != 1 && coneDirection.z != -1))
{
Vector3f rotateAxis = coneDirection.cross(coneDirection, new Vector3f(0, 0, 1));
rotateAxis.normalize();
float rotateAngle = (float) Math.acos(coneDirection.dot(new Vector3f(0, 0, 1)));
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.rotate(-rotateAngle, rotateAxis);
rotationMatrix.transform(direction, direction);
}
else if (coneDirection.z == -1)
{ direction.z *= -1; }
return Maths.Vec4ToVec3(direction);
}
private Vector3f generateRandomUnitVector()
{
float theta = (float) (random.nextFloat() * 2f * Math.PI);
float z = (random.nextFloat() * 2) - 1;
float rootOneMinusZSquared = (float) Math.sqrt(1 - z * z);
float x = (float) (rootOneMinusZSquared * Math.cos(theta));
float y = (float) (rootOneMinusZSquared * Math.sin(theta));
return new Vector3f(x, y, z);
}
}

View File

@ -1,31 +0,0 @@
package io.github.hydos.ginger.engine.postprocessing;
import org.lwjgl.opengl.*;
public class ContrastChanger
{
private ImageRenderer renderer;
private ContrastShader shader;
public ContrastChanger()
{
shader = new ContrastShader();
renderer = new ImageRenderer();
}
public void render(int texture)
{
shader.start();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
System.out.println(texture);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
renderer.renderQuad();
shader.stop();
}
public void cleanUp()
{
renderer.cleanUp();
shader.cleanUp();
}
}

View File

@ -1,150 +0,0 @@
package io.github.hydos.ginger.engine.postprocessing;
import java.nio.ByteBuffer;
import org.lwjgl.opengl.*;
import com.github.halotroop.litecraft.LiteCraftMain;
public class Fbo
{
public static final int NONE = 0;
public static final int DEPTH_TEXTURE = 1;
public static final int DEPTH_RENDER_BUFFER = 2;
private final int width;
private final int height;
private int frameBuffer;
private int colourTexture;
private int depthTexture;
private int depthBuffer;
private int colourBuffer;
/** Creates an FBO of a specified width and height, with the desired type of
* depth buffer attachment.
*
* @param width
* - the width of the FBO.
* @param height
* - the height of the FBO.
* @param depthBufferType
* - an int indicating the type of depth buffer attachment that
* this FBO should use. */
public Fbo(int width, int height, int depthBufferType)
{
this.width = width;
this.height = height;
initialiseFrameBuffer(depthBufferType);
}
/** Deletes the frame buffer and its attachments when the game closes. */
public void cleanUp()
{
GL30.glDeleteFramebuffers(frameBuffer);
GL11.glDeleteTextures(colourTexture);
GL11.glDeleteTextures(depthTexture);
GL30.glDeleteRenderbuffers(depthBuffer);
GL30.glDeleteRenderbuffers(colourBuffer);
}
/** Binds the frame buffer, setting it as the current render target. Anything
* rendered after this will be rendered to this FBO, and not to the screen. */
public void bindFrameBuffer()
{
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
GL11.glViewport(0, 0, width, height);
}
/** Unbinds the frame buffer, setting the default frame buffer as the current
* render target. Anything rendered after this will be rendered to the
* screen, and not this FBO. */
public void unbindFrameBuffer()
{
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glViewport(0, 0, LiteCraftMain.width, LiteCraftMain.height);
}
/** Binds the current FBO to be read from (not used in tutorial 43). */
public void bindToRead()
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, frameBuffer);
GL11.glReadBuffer(GL30.GL_COLOR_ATTACHMENT0);
}
/** @return The ID of the texture containing the colour buffer of the FBO. */
public int getColourTexture()
{ return colourTexture; }
/** @return The texture containing the FBOs depth buffer. */
public int getDepthTexture()
{ return depthTexture; }
/** Creates the FBO along with a colour buffer texture attachment, and
* possibly a depth buffer.
*
* @param type
* - the type of depth buffer attachment to be attached to the
* FBO. */
private void initialiseFrameBuffer(int type)
{
createFrameBuffer();
createTextureAttachment();
if (type == DEPTH_RENDER_BUFFER)
{
createDepthBufferAttachment();
}
else if (type == DEPTH_TEXTURE)
{ createDepthTextureAttachment(); }
unbindFrameBuffer();
}
/** Creates a new frame buffer object and sets the buffer to which drawing
* will occur - colour attachment 0. This is the attachment where the colour
* buffer texture is. */
private void createFrameBuffer()
{
frameBuffer = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
GL11.glDrawBuffer(GL30.GL_COLOR_ATTACHMENT0);
}
/** Creates a texture and sets it as the colour buffer attachment for this
* FBO. */
private void createTextureAttachment()
{
colourTexture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, colourTexture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA8, width, height, 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE,
(ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_COLOR_ATTACHMENT0, GL11.GL_TEXTURE_2D, colourTexture,
0);
}
/** Adds a depth buffer to the FBO in the form of a texture, which can later
* be sampled. */
private void createDepthTextureAttachment()
{
depthTexture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, depthTexture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT24, width, height, 0, GL11.GL_DEPTH_COMPONENT,
GL11.GL_FLOAT, (ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
GL30.glFramebufferTexture2D(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, depthTexture, 0);
}
/** Adds a depth buffer to the FBO in the form of a render buffer. This can't
* be used for sampling in the shaders. */
private void createDepthBufferAttachment()
{
depthBuffer = GL30.glGenRenderbuffers();
GL30.glBindRenderbuffer(GL30.GL_RENDERBUFFER, depthBuffer);
GL30.glRenderbufferStorage(GL30.GL_RENDERBUFFER, GL14.GL_DEPTH_COMPONENT24, width, height);
GL30.glFramebufferRenderbuffer(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL30.GL_RENDERBUFFER,
depthBuffer);
}
}

View File

@ -1,46 +0,0 @@
package io.github.hydos.ginger.engine.postprocessing;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.utils.Loader;
public class PostProcessing
{
private static final float[] POSITIONS =
{
-1, 1, -1, -1, 1, 1, 1, -1
};
private static RawModel quad;
private static ContrastChanger contrastChanger;
public static void init()
{
quad = Loader.loadToVAO(POSITIONS, 2);
contrastChanger = new ContrastChanger();
}
public static void doPostProcessing(int colourTexture)
{
start();
contrastChanger.render(colourTexture);
end();
}
public static void cleanUp()
{ contrastChanger.cleanUp(); }
private static void start()
{
GL30.glBindVertexArray(quad.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glDisable(GL11.GL_DEPTH_TEST);
}
private static void end()
{
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
}
}

View File

@ -1,189 +0,0 @@
package io.github.hydos.ginger.engine.render;
import java.lang.Math;
import java.util.*;
import org.joml.*;
import org.lwjgl.opengl.*;
import com.github.halotroop.litecraft.LiteCraftMain;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.GuiTexture;
import io.github.hydos.ginger.engine.elements.objects.*;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.render.models.TexturedModel;
import io.github.hydos.ginger.engine.render.renderers.*;
import io.github.hydos.ginger.engine.render.shaders.*;
import io.github.hydos.ginger.engine.shadow.ShadowMapMasterRenderer;
import io.github.hydos.ginger.engine.terrain.Terrain;
public class MasterRenderer
{
private StaticShader entityShader;
private EntityRenderer entityRenderer;
private TerrainShader terrainShader;
private TerrainRenderer terrainRenderer;
private GuiShader guiShader;
private GuiRenderer guiRenderer;
private SkyboxRenderer skyboxRenderer;
private NormalMappingRenderer normalRenderer;
private Matrix4f projectionMatrix;
private ShadowMapMasterRenderer shadowMapRenderer;
private Map<TexturedModel, List<Entity>> entities = new HashMap<TexturedModel, List<Entity>>();
private Map<TexturedModel, List<Entity>> normalMapEntities = new HashMap<TexturedModel, List<Entity>>();
public static final float FOV = 70f;
public static final float NEAR_PLANE = 0.1f;
private static final float FAR_PLANE = 1000f;
public MasterRenderer(ThirdPersonCamera camera)
{
createProjectionMatrix();
entityShader = new StaticShader();
entityRenderer = new EntityRenderer(entityShader, projectionMatrix);
skyboxRenderer = new SkyboxRenderer(projectionMatrix);
guiShader = new GuiShader();
guiRenderer = new GuiRenderer(guiShader);
normalRenderer = new NormalMappingRenderer(projectionMatrix);
terrainShader = new TerrainShader();
terrainRenderer = new TerrainRenderer(terrainShader, projectionMatrix);
shadowMapRenderer = new ShadowMapMasterRenderer(camera);
}
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()
{
GL13.glActiveTexture(GL13.GL_TEXTURE5);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, shadowMapRenderer.getShadowMap());
}
public void renderScene(List<Entity> entities, List<Entity> normalEntities, List<Terrain> terrains, List<Light> lights, ThirdPersonCamera camera, Vector4f clipPlane)
{
prepare();
renderEntities(entities, camera, lights);
renderNormalEntities(normalEntities, lights, camera, clipPlane);
renderTerrains(terrains, lights, camera);
skyboxRenderer.render(camera);
}
private void renderNormalEntities(List<Entity> normalEntities, List<Light> lights, ThirdPersonCamera camera, Vector4f clipPlane)
{
for (Entity entity : normalEntities)
{ processEntityWithNormal(entity); }
normalRenderer.render(normalMapEntities, clipPlane, lights, camera);
}
public void renderGuis(List<GuiTexture> guis)
{ guiRenderer.render(guis); }
private void renderTerrains(List<Terrain> terrains, List<Light> lights, ThirdPersonCamera camera)
{
terrainShader.start();
terrainShader.loadSkyColour(Window.getColour());
terrainShader.loadLights(lights);
terrainShader.loadViewMatrix(camera);
terrainRenderer.render(terrains, shadowMapRenderer.getToShadowMapSpaceMatrix());
terrainShader.stop();
}
private void renderEntities(List<Entity> entities, ThirdPersonCamera camera, List<Light> lights)
{
for (Entity entity : entities)
{ processEntity(entity); }
entityRenderer.prepare();
entityShader.start();
entityShader.loadSkyColour(Window.getColour());
entityShader.loadLights(lights);
entityShader.loadViewMatrix(camera);
entityRenderer.render(this.entities);
entityShader.stop();
this.entities.clear();
}
private 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 processEntityWithNormal(Entity entity)
{
TexturedModel entityModel = entity.getModel();
List<Entity> batch = normalMapEntities.get(entityModel);
if (batch != null)
{
batch.add(entity);
}
else
{
List<Entity> newBatch = new ArrayList<Entity>();
newBatch.add(entity);
normalMapEntities.put(entityModel, newBatch);
}
}
public void renderShadowMap(List<Entity> entityList, Light sun)
{
for (Entity entity : entityList)
{ processEntity(entity); }
shadowMapRenderer.render(entities, sun);
entities.clear();
}
public int getShadowMapTexture()
{ return shadowMapRenderer.getShadowMap(); }
public void cleanUp()
{
entityShader.cleanUp();
terrainShader.cleanUp();
guiRenderer.cleanUp();
shadowMapRenderer.cleanUp();
normalRenderer.cleanUp();
}
public Matrix4f getProjectionMatrix()
{ return this.projectionMatrix; }
private void createProjectionMatrix()
{
projectionMatrix = new Matrix4f();
float aspectRatio = (float) LiteCraftMain.width / (float) LiteCraftMain.height;
float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))));
float x_scale = y_scale / aspectRatio;
float frustum_length = FAR_PLANE - NEAR_PLANE;
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 renderGui(GuiTexture guiTexture)
{
if (guiTexture == null) return;
if (guiTexture.getTexture() == 0) return;
List<GuiTexture> texture = new ArrayList<GuiTexture>();
texture.add(guiTexture);
guiRenderer.render(texture);
}
}

View File

@ -1,80 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.util.*;
import org.joml.Matrix4f;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.elements.objects.Entity;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.MasterRenderer;
import io.github.hydos.ginger.engine.render.models.*;
import io.github.hydos.ginger.engine.render.shaders.StaticShader;
import io.github.hydos.ginger.engine.render.texture.ModelTexture;
public class EntityRenderer
{
private StaticShader shader;
public EntityRenderer(StaticShader shader, Matrix4f projectionMatrix)
{
this.shader = shader;
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.stop();
}
public void render(Map<TexturedModel, List<Entity>> entities)
{
for (TexturedModel model : entities.keySet())
{
prepareTexturedModel(model);
List<Entity> batch = entities.get(model);
for (Entity entity : batch)
{
prepareInstance(entity);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}
unbindTexturedModel();
}
}
private void prepareTexturedModel(TexturedModel model)
{
RawModel rawModel = model.getRawModel();
GL30.glBindVertexArray(rawModel.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
ModelTexture texture = model.getTexture();
if (texture.isTransparent())
{
MasterRenderer.disableCulling();
}
else
{
MasterRenderer.enableCulling();
}
shader.loadFakeLightingVariable(texture.isUseFakeLighting());
shader.loadShine(texture.getShineDamper(), texture.getReflectivity());
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getTextureID());
}
private void unbindTexturedModel()
{
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
private void prepareInstance(Entity entity)
{
Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
shader.loadTransformationMatrix(transformationMatrix);
}
public void prepare()
{ GL11.glEnable(GL11.GL_DEPTH_TEST); }
}

View File

@ -1,61 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.util.*;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.font.*;
import io.github.hydos.ginger.engine.render.shaders.FontShader;
public class FontRenderer
{
private FontShader shader;
public FontRenderer()
{ shader = new FontShader(); }
public void render(Map<FontType, List<GUIText>> texts)
{
prepare();
for (FontType font : texts.keySet())
{
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, font.getTextureAtlas());
for (GUIText text : texts.get(font))
{ renderText(text); }
}
endRendering();
}
public void cleanUp()
{ shader.cleanUp(); }
private void prepare()
{
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_DEPTH_TEST);
shader.start();
}
private void renderText(GUIText text)
{
GL30.glBindVertexArray(text.getMesh());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
shader.loadColour(text.getColour());
shader.loadTranslation(text.getPosition());
shader.loadText(text);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, text.getVertexCount());
GL30.glBindVertexArray(0);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
}
private void endRendering()
{
shader.stop();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_BLEND);
}
}

View File

@ -1,54 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.util.List;
import org.joml.Matrix4f;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.elements.GuiTexture;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.render.shaders.GuiShader;
import io.github.hydos.ginger.engine.utils.Loader;
public class GuiRenderer
{
private final RawModel quad;
private GuiShader shader;
public GuiRenderer(GuiShader shader)
{
this.shader = shader;
float[] positions =
{
-1, 1, -1, -1, 1, 1, 1, -1
};
quad = Loader.loadToVAO(positions, 2);
}
public void render(List<GuiTexture> guis)
{
shader.start();
GL30.glBindVertexArray(quad.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL11.glEnable(GL11.GL_BLEND);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
for (GuiTexture gui : guis)
{
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, gui.getTexture());
Matrix4f matrix = Maths.createTransformationMatrix(gui.getPosition(), gui.getScale());
shader.loadTransformation(matrix);
GL11.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount());
}
GL11.glDisable(GL11.GL_BLEND);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
shader.stop();
}
public void cleanUp()
{ shader.cleanUp(); }
}

View File

@ -1,97 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.util.*;
import org.joml.*;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.objects.*;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.MasterRenderer;
import io.github.hydos.ginger.engine.render.models.*;
import io.github.hydos.ginger.engine.render.shaders.NormalMappingShader;
import io.github.hydos.ginger.engine.render.texture.ModelTexture;
public class NormalMappingRenderer
{
private NormalMappingShader shader;
public NormalMappingRenderer(Matrix4f projectionMatrix)
{
this.shader = new NormalMappingShader();
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.connectTextureUnits();
shader.stop();
}
public void render(Map<TexturedModel, List<Entity>> entities, Vector4f clipPlane, List<Light> lights, ThirdPersonCamera camera)
{
shader.start();
prepare(clipPlane, lights, camera);
for (TexturedModel model : entities.keySet())
{
prepareTexturedModel(model);
List<Entity> batch = entities.get(model);
for (Entity entity : batch)
{
prepareInstance(entity);
GL11.glDrawElements(GL11.GL_TRIANGLES, model.getRawModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
}
unbindTexturedModel();
}
shader.stop();
entities.clear();
}
public void cleanUp()
{ shader.cleanUp(); }
private void prepareTexturedModel(TexturedModel model)
{
RawModel rawModel = model.getRawModel();
GL30.glBindVertexArray(rawModel.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL20.glEnableVertexAttribArray(3);
ModelTexture texture = model.getTexture();
if (texture.isTransparent())
{ MasterRenderer.disableCulling(); }
shader.loadShineVariables(texture.getShineDamper(), texture.getReflectivity());
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getTextureID());
GL13.glActiveTexture(GL13.GL_TEXTURE1);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getNormalMap());
}
private void unbindTexturedModel()
{
MasterRenderer.enableCulling();
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL20.glDisableVertexAttribArray(3);
GL30.glBindVertexArray(0);
}
private void prepareInstance(Entity entity)
{
Matrix4f transformationMatrix = Maths.createTransformationMatrix(entity.getPosition(), entity.getRotX(),
entity.getRotY(), entity.getRotZ(), entity.getScale());
shader.loadTransformationMatrix(transformationMatrix);
shader.loadOffset(0, 0);
}
private void prepare(Vector4f clipPlane, List<Light> lights, ThirdPersonCamera camera)
{
shader.loadClipPlane(clipPlane);
//need to be public variables in MasterRenderer
shader.loadSkyColour(Window.getColour());
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
shader.loadLights(lights, viewMatrix);
shader.loadViewMatrix(viewMatrix);
}
}

View File

@ -1,156 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.lang.Math;
import java.nio.FloatBuffer;
import java.util.*;
import org.joml.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.particle.*;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.render.shaders.ParticleShader;
import io.github.hydos.ginger.engine.utils.Loader;
public class ParticleRenderer
{
private static final float[] VERTICES =
{
-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f
};
private static final int MAX_INSTANCES = 10000;
private static final int INSTANCE_DATA_LENGTH = 21;
private static final FloatBuffer buffer = BufferUtils.createFloatBuffer(MAX_INSTANCES * INSTANCE_DATA_LENGTH);
private RawModel quad;
private ParticleShader shader;
private int vbo;
private int pointer;
public ParticleRenderer(Matrix4f projectionMatrix)
{
quad = Loader.loadToVAO(VERTICES, 2);
this.vbo = Loader.createEmptyVbo(INSTANCE_DATA_LENGTH * MAX_INSTANCES);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 1, 4, INSTANCE_DATA_LENGTH, 0);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 2, 4, INSTANCE_DATA_LENGTH, 4);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 3, 4, INSTANCE_DATA_LENGTH, 8);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 4, 4, INSTANCE_DATA_LENGTH, 12);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 5, 4, INSTANCE_DATA_LENGTH, 16);
Loader.addInstancedAttribute(quad.getVaoID(), vbo, 6, 1, INSTANCE_DATA_LENGTH, 20);
shader = new ParticleShader();
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.stop();
}
public void render(Map<ParticleTexture, List<Particle>> particles, ThirdPersonCamera camera)
{
Matrix4f viewMatrix = Maths.createViewMatrix(camera);
prepare();
for (ParticleTexture texture : particles.keySet())
{
bindTexture(texture);
List<Particle> particleList = particles.get(texture);
pointer = 0;
float[] vboData = new float[particleList.size() * INSTANCE_DATA_LENGTH];
for (Particle particle : particleList)
{
updateModelViewMatrix(particle.getPosition(), particle.getRotation(), particle.getScale().x, viewMatrix, vboData);
updateTexCoordInfo(particle, vboData);
}
Loader.updateVbo(vbo, vboData, buffer);
GL31.glDrawArraysInstanced(GL11.GL_TRIANGLE_STRIP, 0, quad.getVertexCount(), particleList.size());
}
finishRendering();
}
public void cleanUp()
{ shader.cleanUp(); }
private void updateTexCoordInfo(Particle particle, float[] data)
{
data[pointer++] = particle.getTexOffset1().x;
data[pointer++] = particle.getTexOffset1().y;
data[pointer++] = particle.getTexOffset2().x;
data[pointer++] = particle.getTexOffset2().y;
data[pointer++] = particle.getBlend();
}
private void bindTexture(ParticleTexture texture)
{
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture.getTextureID());
shader.loadNumberOfRows(texture.getNumberOfRows());
}
private void updateModelViewMatrix(Vector3f position, float rotation, float scale, Matrix4f viewMatrix, float[] vboData)
{
Matrix4f modelMatrix = new Matrix4f();
modelMatrix.translate(position, modelMatrix);
modelMatrix.m00(viewMatrix.m00());
modelMatrix.m01(viewMatrix.m10());
modelMatrix.m02(viewMatrix.m20());
modelMatrix.m10(viewMatrix.m01());
modelMatrix.m11(viewMatrix.m11());
modelMatrix.m12(viewMatrix.m21());
modelMatrix.m20(viewMatrix.m02());
modelMatrix.m21(viewMatrix.m12());
modelMatrix.m22(viewMatrix.m22());
modelMatrix.rotate((float) Math.toRadians(rotation), new Vector3f(0, 0, 1), modelMatrix);
modelMatrix.scale(new Vector3f(scale, scale, scale), modelMatrix);
Matrix4f modelViewMatrix = new Matrix4f();
modelViewMatrix.mul(viewMatrix, modelMatrix);
storeMatrixData(modelViewMatrix, vboData);
}
private void storeMatrixData(Matrix4f matrix, float[] vboData)
{
vboData[pointer++] = matrix.m00();
vboData[pointer++] = matrix.m01();
vboData[pointer++] = matrix.m02();
vboData[pointer++] = matrix.m03();
vboData[pointer++] = matrix.m10();
vboData[pointer++] = matrix.m11();
vboData[pointer++] = matrix.m12();
vboData[pointer++] = matrix.m13();
vboData[pointer++] = matrix.m20();
vboData[pointer++] = matrix.m21();
vboData[pointer++] = matrix.m22();
vboData[pointer++] = matrix.m23();
vboData[pointer++] = matrix.m30();
vboData[pointer++] = matrix.m31();
vboData[pointer++] = matrix.m32();
vboData[pointer++] = matrix.m33();
}
private void prepare()
{
shader.start();
GL30.glBindVertexArray(quad.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
GL20.glEnableVertexAttribArray(3);
GL20.glEnableVertexAttribArray(4);
GL20.glEnableVertexAttribArray(5);
GL20.glEnableVertexAttribArray(6);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);//TODO: add all particle effects into 1 texture to fix overlapping
}
private void finishRendering()
{
shader.stop();
GL30.glBindVertexArray(0);
GL11.glDisable(GL11.GL_BLEND);
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL20.glDisableVertexAttribArray(3);
GL20.glDisableVertexAttribArray(4);
GL20.glDisableVertexAttribArray(5);
GL20.glDisableVertexAttribArray(6);
}
}

View File

@ -1,87 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import org.joml.Matrix4f;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.render.shaders.SkyboxShader;
import io.github.hydos.ginger.engine.utils.Loader;
public class SkyboxRenderer
{
private static final float SIZE = 50f;
private static final float[] VERTICES =
{
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
SIZE, SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, -SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, SIZE, SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
SIZE, -SIZE, SIZE,
-SIZE, -SIZE, SIZE,
-SIZE, SIZE, -SIZE,
SIZE, SIZE, -SIZE,
SIZE, SIZE, SIZE,
SIZE, SIZE, SIZE,
-SIZE, SIZE, SIZE,
-SIZE, SIZE, -SIZE,
-SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, -SIZE,
SIZE, -SIZE, -SIZE,
-SIZE, -SIZE, SIZE,
SIZE, -SIZE, SIZE
};
private static String[] TEXTURE_FILES =
{
"right.png", "left.png", "up.png", "down.png", "back.png", "front.png"
};
private RawModel cube;
private int texture;
private SkyboxShader shader;
public SkyboxRenderer(Matrix4f projectionMatrix)
{
cube = Loader.loadToVAO(VERTICES, 3);
texture = Loader.loadCubeMap(TEXTURE_FILES);
shader = new SkyboxShader();
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.stop();
}
public void render(ThirdPersonCamera camera)
{
shader.start();
shader.loadViewMatrix(camera);
GL30.glBindVertexArray(cube.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texture);
GL11.glDrawArrays(GL11.GL_TRIANGLES, 0, cube.getVertexCount());
GL20.glDisableVertexAttribArray(0);
GL30.glBindVertexArray(0);
shader.stop();
}
public void cleanUp()
{ shader.cleanUp(); }
}

View File

@ -1,78 +0,0 @@
package io.github.hydos.ginger.engine.render.renderers;
import java.util.List;
import org.joml.*;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.render.shaders.TerrainShader;
import io.github.hydos.ginger.engine.terrain.*;
public class TerrainRenderer
{
private TerrainShader shader;
public TerrainRenderer(TerrainShader shader, Matrix4f projectionMatrix)
{
this.shader = shader;
shader.start();
shader.loadProjectionMatrix(projectionMatrix);
shader.connectTextureUnits();
shader.stop();
}
public void render(List<Terrain> terrains, Matrix4f toShadowSpace)
{
shader.loadToShadowMapSpace(toShadowSpace);
for (Terrain t : terrains)
{
prepareTerrain(t);
loadModelMatrix(t);
GL11.glDrawElements(GL11.GL_TRIANGLES, t.getModel().getVertexCount(), GL11.GL_UNSIGNED_INT, 0);
unbindTerrain();
}
}
private void prepareTerrain(Terrain terrain)
{
RawModel rawModel = terrain.getModel();
GL30.glBindVertexArray(rawModel.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
GL20.glEnableVertexAttribArray(2);
bindTextures(terrain);
shader.loadShine(1, 0);
}
private void bindTextures(Terrain terrain)
{
TerrainTexturePack texturePack = terrain.getTexturePack();
TerrainTexture blendMap = terrain.getBlendMap();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturePack.getBackgroundTexture().getTextureID());
GL13.glActiveTexture(GL13.GL_TEXTURE1);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturePack.getrTexture().getTextureID());
GL13.glActiveTexture(GL13.GL_TEXTURE2);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturePack.getgTexture().getTextureID());
GL13.glActiveTexture(GL13.GL_TEXTURE3);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texturePack.getbTexture().getTextureID());
GL13.glActiveTexture(GL13.GL_TEXTURE4);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, blendMap.getTextureID());
}
private void unbindTerrain()
{
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL20.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
private void loadModelMatrix(Terrain terrain)
{
Matrix4f transformationMatrix = Maths.createTransformationMatrix(new Vector3f(terrain.getX(), 0, terrain.getZ()), 0, 0, 0, new Vector3f(1, 1, 1));
shader.loadTransformationMatrix(transformationMatrix);
}
}

View File

@ -1,52 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import org.joml.*;
import io.github.hydos.ginger.engine.font.GUIText;
public class FontShader extends ShaderProgram
{
private static final String VERTEX_FILE = "fontVertexShader.glsl";
private static final String FRAGMENT_FILE = "fontFragmentShader.glsl";
private int location_colour;
private int location_translation;
private int location_borderWidth;
private int location_borderEdge;
private int location_offset;
private int location_outlineColour;
public FontShader()
{ super(VERTEX_FILE, FRAGMENT_FILE); }
@Override
protected void getAllUniformLocations()
{
location_colour = super.getUniformLocation("colour");
location_translation = super.getUniformLocation("translation");
location_borderWidth = super.getUniformLocation("borderWidth");
location_borderEdge = super.getUniformLocation("borderEdge");
location_offset = super.getUniformLocation("offset");
location_outlineColour = super.getUniformLocation("outlineColour");
}
@Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
}
public void loadColour(Vector3f colour)
{ super.loadVector(location_colour, colour); }
public void loadTranslation(Vector2f translation)
{ super.load2DVector(location_translation, translation); }
public void loadText(GUIText text)
{
super.load2DVector(location_offset, text.getOffset());
super.loadFloat(location_borderEdge, text.getBorderEdge());
super.loadFloat(location_borderWidth, text.getBorderWidth());
super.loadVector(location_outlineColour, text.getOutlineColour());
}
}

View File

@ -1,129 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import java.util.List;
import org.joml.*;
import io.github.hydos.ginger.engine.elements.objects.Light;
import io.github.hydos.ginger.engine.math.Maths;
public class NormalMappingShader extends ShaderProgram
{
private static final int MAX_LIGHTS = 4;
private static final String VERTEX_FILE = "normalMapVertexShader.glsl";
private static final String FRAGMENT_FILE = "normalMapFragmentShader.glsl";
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightPositionEyeSpace[];
private int location_lightColour[];
private int location_attenuation[];
private int location_shineDamper;
private int location_reflectivity;
private int location_skyColour;
private int location_numberOfRows;
private int location_offset;
private int location_plane;
private int location_modelTexture;
private int location_normalMap;
public NormalMappingShader()
{ super(VERTEX_FILE, FRAGMENT_FILE); }
@Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoordinates");
super.bindAttribute(2, "normal");
super.bindAttribute(3, "tangent");
}
@Override
protected void getAllUniformLocations()
{
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_shineDamper = super.getUniformLocation("shineDamper");
location_reflectivity = super.getUniformLocation("reflectivity");
location_skyColour = super.getUniformLocation("skyColour");
location_numberOfRows = super.getUniformLocation("numberOfRows");
location_offset = super.getUniformLocation("offset");
location_plane = super.getUniformLocation("plane");
location_modelTexture = super.getUniformLocation("modelTexture");
location_normalMap = super.getUniformLocation("normalMap");
location_lightPositionEyeSpace = new int[MAX_LIGHTS];
location_lightColour = new int[MAX_LIGHTS];
location_attenuation = new int[MAX_LIGHTS];
for (int i = 0; i < MAX_LIGHTS; i++)
{
location_lightPositionEyeSpace[i] = super.getUniformLocation("lightPositionEyeSpace[" + i + "]");
location_lightColour[i] = super.getUniformLocation("lightColour[" + i + "]");
location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
}
}
public void connectTextureUnits()
{
super.loadInt(location_modelTexture, 0);
super.loadInt(location_normalMap, 1);
}
public void loadClipPlane(Vector4f plane)
{ super.loadVector(location_plane, plane); }
public void loadNumberOfRows(int numberOfRows)
{ super.loadFloat(location_numberOfRows, numberOfRows); }
public void loadOffset(float x, float y)
{ super.load2DVector(location_offset, new Vector2f(x, y)); }
public void loadSkyColour(float r, float g, float b)
{ super.loadVector(location_skyColour, new Vector3f(r, g, b)); }
public void loadShineVariables(float damper, float reflectivity)
{
super.loadFloat(location_shineDamper, damper);
super.loadFloat(location_reflectivity, reflectivity);
}
public void loadTransformationMatrix(Matrix4f matrix)
{ super.loadMatrix(location_transformationMatrix, matrix); }
public void loadLights(List<Light> lights, Matrix4f viewMatrix)
{
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (i < lights.size())
{
super.loadVector(location_lightPositionEyeSpace[i], getEyeSpacePosition(lights.get(i), viewMatrix));
super.loadVector(location_lightColour[i], lights.get(i).getColour());
super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
}
else
{
super.loadVector(location_lightPositionEyeSpace[i], new Vector3f(0, 0, 0));
super.loadVector(location_lightColour[i], new Vector3f(0, 0, 0));
super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
}
}
}
public void loadViewMatrix(Matrix4f viewMatrix)
{ super.loadMatrix(location_viewMatrix, viewMatrix); }
public void loadProjectionMatrix(Matrix4f projection)
{ super.loadMatrix(location_projectionMatrix, projection); }
public Vector3f getEyeSpacePosition(Light light, Matrix4f viewMatrix)
{
Vector3f position = light.getPosition();
Vector4f eyeSpacePos = new Vector4f(position.x, position.y, position.z, 1f);
viewMatrix.transform(eyeSpacePos, eyeSpacePos);
return Maths.Vec4ToVec3(eyeSpacePos);
}
public void loadSkyColour(Vector3f colour)
{ super.loadVector(location_skyColour, colour); }
}

View File

@ -1,113 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import java.io.*;
import java.nio.FloatBuffer;
import org.joml.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
public abstract class ShaderProgram
{
private int programID;
private int vertexShaderID;
private int fragmentShaderID;
private static FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16);
public ShaderProgram(String vertexFile, String fragmentFile)
{
vertexShaderID = loadShader(vertexFile, GL20.GL_VERTEX_SHADER);
fragmentShaderID = loadShader(fragmentFile, GL20.GL_FRAGMENT_SHADER);
programID = GL20.glCreateProgram();
GL20.glAttachShader(programID, vertexShaderID);
GL20.glAttachShader(programID, fragmentShaderID);
bindAttributes();
GL20.glLinkProgram(programID);
GL20.glValidateProgram(programID);
getAllUniformLocations();
}
protected abstract void getAllUniformLocations();
protected int getUniformLocation(String uniformName)
{ return GL20.glGetUniformLocation(programID, uniformName); }
public void start()
{ GL20.glUseProgram(programID); }
public void stop()
{ GL20.glUseProgram(0); }
public void cleanUp()
{
stop();
GL20.glDetachShader(programID, vertexShaderID);
GL20.glDetachShader(programID, fragmentShaderID);
GL20.glDeleteShader(vertexShaderID);
GL20.glDeleteShader(fragmentShaderID);
GL20.glDeleteProgram(programID);
}
protected abstract void bindAttributes();
protected void bindAttribute(int attribute, String variableName)
{ GL20.glBindAttribLocation(programID, attribute, variableName); }
protected void loadFloat(int location, float value)
{ GL20.glUniform1f(location, value); }
protected void loadInt(int location, int value)
{ GL20.glUniform1i(location, value); }
protected void loadVector(int location, Vector3f vector)
{ GL20.glUniform3f(location, vector.x, vector.y, vector.z); }
protected void loadVector(int location, Vector4f vector)
{ GL20.glUniform4f(location, vector.x, vector.y, vector.z, vector.w); }
protected void load2DVector(int location, Vector2f vector)
{ GL20.glUniform2f(location, vector.x, vector.y); }
protected void loadBoolean(int location, boolean value)
{
float toLoad = 0;
if (value)
{ toLoad = 1; }
GL20.glUniform1f(location, toLoad);
}
protected void loadMatrix(int location, Matrix4f matrix)
{
matrix = new Matrix4f(matrixBuffer);
matrixBuffer.flip();
GL20.glUniformMatrix4fv(location, false, matrixBuffer);
}
private static int loadShader(String file, int type)
{
StringBuilder shaderSource = new StringBuilder();
try
{
BufferedReader reader = new BufferedReader(new InputStreamReader(ShaderProgram.class.getResourceAsStream("/shaders/" + file)));
String line;
while ((line = reader.readLine()) != null)
{ shaderSource.append(line).append("\n"); }
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
System.exit(-1);
}
int shaderID = GL20.glCreateShader(type);
GL20.glShaderSource(shaderID, shaderSource);
GL20.glCompileShader(shaderID);
if (GL20.glGetShaderi(shaderID, GL20.GL_COMPILE_STATUS) == GL11.GL_FALSE)
{
System.out.println(GL20.glGetShaderInfoLog(shaderID, 500));
System.err.println("Could not compile shader: " + file);
System.exit(-1);
}
return shaderID;
}
}

View File

@ -1,39 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import org.joml.Matrix4f;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.math.Maths;
public class SkyboxShader extends ShaderProgram
{
private int location_projectionMatrix;
private int location_viewMatrix;
public SkyboxShader()
{ super("skyboxVertexShader.glsl", "skyboxFragmentShader.glsl"); }
public void loadProjectionMatrix(Matrix4f matrix)
{ super.loadMatrix(location_projectionMatrix, matrix); }
public void loadViewMatrix(ThirdPersonCamera camera)
{
//TODO: make a vector3f
Matrix4f matrix = Maths.createViewMatrix(camera);
matrix.m30(0);
matrix.m31(0);
matrix.m32(0);
super.loadMatrix(location_viewMatrix, matrix);
}
@Override
protected void getAllUniformLocations()
{
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
}
@Override
protected void bindAttributes()
{ super.bindAttribute(0, "position"); }
}

View File

@ -1,99 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import java.util.List;
import org.joml.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.objects.Light;
import io.github.hydos.ginger.engine.math.Maths;
public class StaticShader extends ShaderProgram
{
private static final int MAX_LIGHTS = 5;
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightColour[];
private int location_lightPosition[];
private int location_attenuation[];
private int location_shineDamper;
private int location_reflectivity;
private int location_useFakeLighting;
private int location_skyColour;
public StaticShader()
{ super("entityVertexShader.glsl", "entityFragmentShader.glsl"); }
@Override
protected void getAllUniformLocations()
{
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_shineDamper = super.getUniformLocation("shineDamper");
location_reflectivity = super.getUniformLocation("reflectivity");
location_useFakeLighting = super.getUniformLocation("useFakeLighting");
location_skyColour = super.getUniformLocation("skyColour");
location_lightPosition = new int[MAX_LIGHTS];
location_lightColour = new int[MAX_LIGHTS];
location_attenuation = new int[MAX_LIGHTS];
for (int i = 0; i < MAX_LIGHTS; i++)
{
location_lightPosition[i] = super.getUniformLocation("lightPosition[" + i + "]");
location_lightColour[i] = super.getUniformLocation("lightColour[" + i + "]");
location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
}
}
@Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
super.bindAttribute(2, "normal");
}
public void loadTransformationMatrix(Matrix4f matrix)
{ super.loadMatrix(location_transformationMatrix, matrix); }
public void loadProjectionMatrix(Matrix4f matrix)
{ super.loadMatrix(location_projectionMatrix, matrix); }
public void loadViewMatrix(ThirdPersonCamera camera)
{
Matrix4f matrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, matrix);
}
public void loadLights(List<Light> lights)
{
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (i < lights.size())
{
super.loadVector(location_lightPosition[i], lights.get(i).getPosition());
super.loadVector(location_lightColour[i], lights.get(i).getColour());
super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
}
else
{
super.loadVector(location_lightPosition[i], new Vector3f(0, 0, 0));
super.loadVector(location_lightColour[i], new Vector3f(0, 0, 0));
super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
}
}
}
public void loadShine(float damper, float reflectivity)
{
super.loadFloat(location_shineDamper, damper);
super.loadFloat(location_reflectivity, reflectivity);
}
public void loadFakeLightingVariable(boolean useFake)
{ super.loadBoolean(location_useFakeLighting, useFake); }
public void loadSkyColour(Vector3f colour)
{ super.loadVector(location_skyColour, colour); }
}

View File

@ -1,121 +0,0 @@
package io.github.hydos.ginger.engine.render.shaders;
import java.util.List;
import org.joml.*;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.objects.Light;
import io.github.hydos.ginger.engine.math.Maths;
public class TerrainShader extends ShaderProgram
{
private static final int MAX_LIGHTS = 5;
private int location_transformationMatrix;
private int location_projectionMatrix;
private int location_viewMatrix;
private int location_lightColour[];
private int location_lightPosition[];
private int location_attenuation[];
private int location_shineDamper;
private int location_reflectivity;
private int location_skyColour;
private int location_backgroundTexture;
private int location_rTexture;
private int location_gTexture;
private int location_bTexture;
private int location_blendMap;
private int location_toShadowMapSpace;
private int location_shadowMap;
public TerrainShader()
{ super("terrainVertexShader.glsl", "terrainFragmentShader.glsl"); }
@Override
protected void getAllUniformLocations()
{
location_transformationMatrix = super.getUniformLocation("transformationMatrix");
location_projectionMatrix = super.getUniformLocation("projectionMatrix");
location_viewMatrix = super.getUniformLocation("viewMatrix");
location_lightPosition = new int[MAX_LIGHTS];
location_lightColour = new int[MAX_LIGHTS];
location_attenuation = new int[MAX_LIGHTS];
for (int i = 0; i < MAX_LIGHTS; i++)
{
location_lightPosition[i] = super.getUniformLocation("lightPosition[" + i + "]");
location_lightColour[i] = super.getUniformLocation("lightColour[" + i + "]");
location_attenuation[i] = super.getUniformLocation("attenuation[" + i + "]");
}
location_shineDamper = super.getUniformLocation("shineDamper");
location_reflectivity = super.getUniformLocation("reflectivity");
location_skyColour = super.getUniformLocation("skyColour");
location_backgroundTexture = super.getUniformLocation("backgroundTexture");
location_rTexture = super.getUniformLocation("rTexture");
location_gTexture = super.getUniformLocation("gTexture");
location_bTexture = super.getUniformLocation("bTexture");
location_blendMap = super.getUniformLocation("blendMap");
location_toShadowMapSpace = super.getUniformLocation("toShadowMapSpace");
location_shadowMap = super.getUniformLocation("shadowMap");
}
@Override
protected void bindAttributes()
{
super.bindAttribute(0, "position");
super.bindAttribute(1, "textureCoords");
super.bindAttribute(2, "normal");
}
public void loadTransformationMatrix(Matrix4f matrix)
{ super.loadMatrix(location_transformationMatrix, matrix); }
public void loadProjectionMatrix(Matrix4f matrix)
{ super.loadMatrix(location_projectionMatrix, matrix); }
public void loadViewMatrix(ThirdPersonCamera camera)
{
Matrix4f matrix = Maths.createViewMatrix(camera);
super.loadMatrix(location_viewMatrix, matrix);
}
public void loadLights(List<Light> lights)
{
for (int i = 0; i < MAX_LIGHTS; i++)
{
if (i < lights.size())
{
super.loadVector(location_lightPosition[i], lights.get(i).getPosition());
super.loadVector(location_lightColour[i], lights.get(i).getColour());
super.loadVector(location_attenuation[i], lights.get(i).getAttenuation());
}
else
{
super.loadVector(location_lightPosition[i], new Vector3f(0, 0, 0));
super.loadVector(location_lightColour[i], new Vector3f(0, 0, 0));
super.loadVector(location_attenuation[i], new Vector3f(1, 0, 0));
}
}
}
public void loadShine(float damper, float reflectivity)
{
super.loadFloat(location_shineDamper, damper);
super.loadFloat(location_reflectivity, reflectivity);
}
public void loadSkyColour(Vector3f colour)
{ super.loadVector(location_skyColour, colour); }
public void loadToShadowMapSpace(Matrix4f matrix)
{ super.loadMatrix(location_toShadowMapSpace, matrix); }
public void connectTextureUnits()
{
super.loadInt(location_backgroundTexture, 0);
super.loadInt(location_rTexture, 1);
super.loadInt(location_gTexture, 2);
super.loadInt(location_bTexture, 3);
super.loadInt(location_blendMap, 4);
super.loadInt(location_shadowMap, 5);
}
}

View File

@ -1,96 +0,0 @@
package io.github.hydos.ginger.engine.render.texture;
import static org.lwjgl.stb.STBImage.*;
import static org.lwjgl.system.MemoryStack.stackPush;
import java.io.IOException;
import java.nio.*;
import org.lwjgl.system.MemoryStack;
import io.github.hydos.ginger.engine.render.tools.IOUtil;
public class Image
{
public Image(String imagePath)
{
ByteBuffer img;
ByteBuffer imageBuffer;
try
{
imageBuffer = IOUtil.ioResourceToByteBuffer(imagePath, 8 * 1024);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
try (MemoryStack stack = stackPush())
{
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer comp = stack.mallocInt(1);
// Use info to read image metadata without decoding the entire image.
// We don't need this for this demo, just testing the API.
if (!stbi_info_from_memory(imageBuffer, w, h, comp))
{ throw new RuntimeException("Failed to read image information: " + stbi_failure_reason()); }
// System.out.println("Image width: " + w.get(0));
// System.out.println("Image height: " + h.get(0));
// System.out.println("Image components: " + comp.get(0));
// System.out.println("Image HDR: " + stbi_is_hdr_from_memory(imageBuffer));
// Decode the image
img = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
if (img == null)
{ throw new RuntimeException("Failed to load image: " + stbi_failure_reason()); }
this.image = img;
this.width = w.get(0);
this.height = h.get(0);
}
}
public static Image createImage(String imagePath)
{
ByteBuffer img;
ByteBuffer imageBuffer;
try
{
imageBuffer = IOUtil.ioResourceToByteBuffer(imagePath, 8 * 1024);
}
catch (IOException e)
{
throw new RuntimeException(e);
}
try (MemoryStack stack = stackPush())
{
IntBuffer w = stack.mallocInt(1);
IntBuffer h = stack.mallocInt(1);
IntBuffer comp = stack.mallocInt(1);
// Use info to read image metadata without decoding the entire image.
// We don't need this for this demo, just testing the API.
if (!stbi_info_from_memory(imageBuffer, w, h, comp))
{ throw new RuntimeException("Failed to read image information: " + stbi_failure_reason()); }
img = stbi_load_from_memory(imageBuffer, w, h, comp, 0);
if (img == null)
{ throw new RuntimeException("Failed to load image: " + stbi_failure_reason()); }
return new Image(w.get(0), h.get(0), img);
}
}
public ByteBuffer getImage()
{ return image; }
public int getWidth()
{ return width; }
public int getHeight()
{ return height; }
private ByteBuffer image;
private int width, height;
Image(int width, int heigh, ByteBuffer image)
{
this.image = image;
this.height = heigh;
this.width = width;
}
}

View File

@ -1,76 +0,0 @@
package io.github.hydos.ginger.engine.render.texture;
import org.lwjgl.opengl.*;
public class ModelTexture
{
private int textureID = GL11.glGenTextures();
private boolean transparency = false;
private boolean useFakeLighting = false;
public int numberOfRows = 1;
private int normalMap;
private float shineDamper = 1;
private float reflectivity = 0;
private Image texture;
public ModelTexture(String file)
{
texture = Image.createImage("/textures/" + file);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.textureID);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10241, 9729.0f);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10240, 9729.0f);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, texture.getWidth(), texture.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texture.getImage());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -0.4f);
}
public ModelTexture(Image texture)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.textureID);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10241, 9729.0f);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10240, 9729.0f);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, 6408, texture.getWidth(), texture.getHeight(), 0, 6408, 5121, texture.getImage());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
}
public void remove()
{ GL11.glDeleteTextures(this.textureID); }
public int getTextureID()
{ return this.textureID; }
public Image getTexture()
{ return texture; }
public int getNormalMap()
{ return normalMap; }
public void setNormalMap(int normalMap)
{ this.normalMap = normalMap; }
public float getShineDamper()
{ return shineDamper; }
public float getReflectivity()
{ return reflectivity; }
public void setShineDamper(float shineDamper)
{ this.shineDamper = shineDamper; }
public void setReflectivity(float reflectivity)
{ this.reflectivity = reflectivity; }
public boolean isTransparent()
{ return transparency; }
public void setTransparency(boolean b)
{ this.transparency = b; }
public boolean isUseFakeLighting()
{ return useFakeLighting; }
public void useFakeLighting(boolean useFakeLighting)
{ this.useFakeLighting = useFakeLighting; }
}

View File

@ -1,44 +0,0 @@
package io.github.hydos.ginger.engine.render.tools;
import static org.lwjgl.BufferUtils.createByteBuffer;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import org.lwjgl.BufferUtils;
public class IOUtil
{
private IOUtil()
{}
private static ByteBuffer resizeBuffer(ByteBuffer buffer, int newCapacity)
{
ByteBuffer newBuffer = BufferUtils.createByteBuffer(newCapacity);
buffer.flip();
newBuffer.put(buffer);
return newBuffer;
}
public static ByteBuffer ioResourceToByteBuffer(String resource, int bufferSize) throws IOException
{
ByteBuffer buffer;
try (
InputStream source = IOUtil.class.getResourceAsStream(resource);
ReadableByteChannel rbc = Channels.newChannel(source))
{
buffer = createByteBuffer(bufferSize);
while (true)
{
int bytes = rbc.read(buffer);
if (bytes == -1)
{ break; }
if (buffer.remaining() == 0)
{ buffer = resizeBuffer(buffer, buffer.capacity() * 3 / 2); }
}
}
buffer.flip();
return buffer;
}
}

View File

@ -1,153 +0,0 @@
package io.github.hydos.ginger.engine.render.tools;
import org.joml.*;
import com.github.halotroop.litecraft.LiteCraftMain;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.terrain.Terrain;
public class MousePicker
{
private static final int RECURSION_COUNT = 200;
private static final float RAY_RANGE = 600;
private Vector3f currentRay = new Vector3f();
private Matrix4f projectionMatrix;
private Matrix4f viewMatrix;
private ThirdPersonCamera camera;
private Terrain terrain;
private Vector3f currentTerrainPoint;
public MousePicker(ThirdPersonCamera cam, Matrix4f projection, Terrain terrain)
{
camera = cam;
projectionMatrix = projection;
viewMatrix = Maths.createViewMatrix(camera);
this.terrain = terrain;
}
public Vector3f getCurrentTerrainPoint()
{ return currentTerrainPoint; }
public Vector3f getCurrentRay()
{ return currentRay; }
public void update()
{
viewMatrix = Maths.createViewMatrix(camera);
currentRay = calculateMouseRay();
if (intersectionInRange(0, RAY_RANGE, currentRay))
{
currentTerrainPoint = binarySearch(0, 0, RAY_RANGE, currentRay);
}
else
{
currentTerrainPoint = null;
}
}
private Vector3f calculateMouseRay()
{
float mouseX = (float) Window.getMouseX();
float mouseY = (float) (LiteCraftMain.height - Window.getMouseY());
Vector2f normalizedCoords = getNormalisedDeviceCoordinates(mouseX, mouseY);
Vector4f clipCoords = new Vector4f(normalizedCoords.x, normalizedCoords.y, -1.0f, 1.0f);
Vector4f eyeCoords = toEyeCoords(clipCoords);
Vector3f worldRay = toWorldCoords(eyeCoords);
return worldRay;
}
private Vector3f toWorldCoords(Vector4f eyeCoords)
{
Matrix4f invertedView = viewMatrix.invert(viewMatrix);
Vector4f rayWorld = invertedView.transform(eyeCoords);
Vector3f mouseRay = new Vector3f(rayWorld.x, rayWorld.y, rayWorld.z);
mouseRay.normalize();
return mouseRay;
}
private Vector4f toEyeCoords(Vector4f clipCoords)
{
Matrix4f invertedProjection = projectionMatrix.invert(projectionMatrix);
Vector4f eyeCoords = invertedProjection.transform(clipCoords);
return new Vector4f(eyeCoords.x, eyeCoords.y, -1f, 0f);
}
private Vector2f getNormalisedDeviceCoordinates(float mouseX, float mouseY)
{
float x = (2.0f * mouseX) / LiteCraftMain.width - 1f;
float y = (2.0f * mouseY) / LiteCraftMain.height - 1f;
return new Vector2f(x, y);
}
//**********************************************************
private Vector3f getPointOnRay(Vector3f ray, float distance)
{
Vector3f output = new Vector3f();
Vector3f camPos = camera.getPosition();
Vector3f start = new Vector3f(camPos.x, camPos.y, camPos.z);
Vector3f scaledRay = new Vector3f(ray.x * distance, ray.y * distance, ray.z * distance);
return output.add(start, scaledRay);
}
private Vector3f binarySearch(int count, float start, float finish, Vector3f ray)
{
float half = start + ((finish - start) / 2f);
if (count >= RECURSION_COUNT)
{
Vector3f endPoint = getPointOnRay(ray, half);
Terrain terrain = getTerrain(endPoint.x, endPoint.z);
if (terrain != null)
{
return endPoint;
}
else
{
return null;
}
}
if (intersectionInRange(start, half, ray))
{
return binarySearch(count + 1, start, half, ray);
}
else
{
return binarySearch(count + 1, half, finish, ray);
}
}
private boolean intersectionInRange(float start, float finish, Vector3f ray)
{
Vector3f startPoint = getPointOnRay(ray, start);
Vector3f endPoint = getPointOnRay(ray, finish);
if (!isUnderGround(startPoint) && isUnderGround(endPoint))
{
return true;
}
else
{
return false;
}
}
private boolean isUnderGround(Vector3f testPoint)
{
Terrain terrain = getTerrain(testPoint.x(), testPoint.z());
float height = 0;
if (terrain != null)
{ height = terrain.getHeightOfTerrain(testPoint.x(), testPoint.z()); }
if (testPoint.y < height)
{
return true;
}
else
{
return false;
}
}
private Terrain getTerrain(float worldX, float worldZ)
{ return terrain; }
}

View File

@ -1,218 +0,0 @@
package io.github.hydos.ginger.engine.shadow;
import java.lang.Math;
import org.joml.*;
import com.github.halotroop.litecraft.LiteCraftMain;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.MasterRenderer;
/** Represents the 3D cuboidal area of the world in which objects will cast
* shadows (basically represents the orthographic projection area for the shadow
* render pass). It is updated each frame to optimise the area, making it as
* small as possible (to allow for optimal shadow map resolution) while not
* being too small to avoid objects not having shadows when they should.
* Everything inside the cuboidal area represented by this object will be
* rendered to the shadow map in the shadow render pass. Everything outside the
* area won't be. */
public class ShadowBox
{
private static final float OFFSET = 10;
private static final Vector4f UP = new Vector4f(0, 1, 0, 0);
private static final Vector4f FORWARD = new Vector4f(0, 0, -1, 0);
private static final float SHADOW_DISTANCE = 100;
private float minX, maxX;
private float minY, maxY;
private float minZ, maxZ;
private Matrix4f lightViewMatrix;
private ThirdPersonCamera cam;
private float farHeight, farWidth, nearHeight, nearWidth;
/** Creates a new shadow box and calculates some initial values relating to
* the camera's view frustum, namely the width and height of the near plane
* and (possibly adjusted) far plane.
*
* @param lightViewMatrix
* - basically the "view matrix" of the light. Can be used to
* transform a point from world space into "light" space (i.e.
* changes a point's coordinates from being in relation to the
* world's axis to being in terms of the light's local axis).
* @param camera
* - the in-game camera. */
protected ShadowBox(Matrix4f lightViewMatrix, ThirdPersonCamera camera)
{
this.lightViewMatrix = lightViewMatrix;
this.cam = camera;
calculateWidthsAndHeights();
}
/** Updates the bounds of the shadow box based on the light direction and the
* camera's view frustum, to make sure that the box covers the smallest area
* possible while still ensuring that everything inside the camera's view
* (within a certain range) will cast shadows. */
protected void update()
{
Matrix4f rotation = calculateCameraRotationMatrix();
Vector3f forwardVector = Maths.Vec4ToVec3(rotation.transform(FORWARD));
Vector3f toFar = new Vector3f(forwardVector);
Maths.scale(toFar, SHADOW_DISTANCE);
Vector3f toNear = new Vector3f(forwardVector);
Maths.scale(toNear, MasterRenderer.NEAR_PLANE);
Vector3f centerNear = new Vector3f().add(toNear, cam.getPosition());
Vector3f centerFar = new Vector3f().add(toFar, cam.getPosition());
Vector4f[] points = calculateFrustumVertices(rotation, forwardVector, centerNear,
centerFar);
boolean first = true;
for (Vector4f point : points)
{
if (first)
{
minX = point.x;
maxX = point.x;
minY = point.y;
maxY = point.y;
minZ = point.z;
maxZ = point.z;
first = false;
continue;
}
if (point.x > maxX)
{
maxX = point.x;
}
else if (point.x < minX)
{ minX = point.x; }
if (point.y > maxY)
{
maxY = point.y;
}
else if (point.y < minY)
{ minY = point.y; }
if (point.z > maxZ)
{
maxZ = point.z;
}
else if (point.z < minZ)
{ minZ = point.z; }
}
maxZ += OFFSET;
}
/** Calculates the center of the "view cuboid" in light space first, and then
* converts this to world space using the inverse light's view matrix.
*
* @return The center of the "view cuboid" in world space. */
protected Vector3f getCenter()
{
float x = (minX + maxX) / 2f;
float y = (minY + maxY) / 2f;
float z = (minZ + maxZ) / 2f;
Vector4f cen = new Vector4f(x, y, z, 1);
Matrix4f invertedLight = new Matrix4f();
invertedLight = new Matrix4f().invert(lightViewMatrix);
return Maths.Vec4ToVec3(invertedLight.transform(cen));
}
/** @return The width of the "view cuboid" (orthographic projection area). */
protected float getWidth()
{ return maxX - minX; }
/** @return The height of the "view cuboid" (orthographic projection area). */
protected float getHeight()
{ return maxY - minY; }
/** @return The length of the "view cuboid" (orthographic projection area). */
protected float getLength()
{ return maxZ - minZ; }
/** Calculates the position of the vertex at each corner of the view frustum
* in light space (8 vertices in total, so this returns 8 positions).
*
* @param rotation
* - camera's rotation.
* @param forwardVector
* - the direction that the camera is aiming, and thus the
* direction of the frustum.
* @param centerNear
* - the center point of the frustum's near plane.
* @param centerFar
* - the center point of the frustum's (possibly adjusted) far
* plane.
* @return The positions of the vertices of the frustum in light space. */
private Vector4f[] calculateFrustumVertices(Matrix4f rotation, Vector3f forwardVector,
Vector3f centerNear, Vector3f centerFar)
{
Matrix4f upMatrix = rotation;
Vector3f upVector = Maths.Vec4ToVec3(upMatrix.transform(UP));
Vector3f rightVector = new Vector3f().cross(forwardVector, upVector);
Vector3f downVector = new Vector3f(-upVector.x, -upVector.y, -upVector.z);
Vector3f leftVector = new Vector3f(-rightVector.x, -rightVector.y, -rightVector.z);
Vector3f farTop = new Vector3f().add(centerFar, new Vector3f(upVector.x * farHeight,
upVector.y * farHeight, upVector.z * farHeight));
Vector3f farBottom = new Vector3f().add(centerFar, new Vector3f(downVector.x * farHeight,
downVector.y * farHeight, downVector.z * farHeight));
Vector3f nearTop = new Vector3f().add(centerNear, new Vector3f(upVector.x * nearHeight,
upVector.y * nearHeight, upVector.z * nearHeight));
Vector3f nearBottom = new Vector3f().add(centerNear, new Vector3f(downVector.x * nearHeight,
downVector.y * nearHeight, downVector.z * nearHeight));
Vector4f[] points = new Vector4f[8];
points[0] = calculateLightSpaceFrustumCorner(farTop, rightVector, farWidth);
points[1] = calculateLightSpaceFrustumCorner(farTop, leftVector, farWidth);
points[2] = calculateLightSpaceFrustumCorner(farBottom, rightVector, farWidth);
points[3] = calculateLightSpaceFrustumCorner(farBottom, leftVector, farWidth);
points[4] = calculateLightSpaceFrustumCorner(nearTop, rightVector, nearWidth);
points[5] = calculateLightSpaceFrustumCorner(nearTop, leftVector, nearWidth);
points[6] = calculateLightSpaceFrustumCorner(nearBottom, rightVector, nearWidth);
points[7] = calculateLightSpaceFrustumCorner(nearBottom, leftVector, nearWidth);
return points;
}
/** Calculates one of the corner vertices of the view frustum in world space
* and converts it to light space.
*
* @param startPoint
* - the starting center point on the view frustum.
* @param direction
* - the direction of the corner from the start point.
* @param width
* - the distance of the corner from the start point.
* @return - The relevant corner vertex of the view frustum in light space. */
private Vector4f calculateLightSpaceFrustumCorner(Vector3f startPoint, Vector3f direction,
float width)
{
Vector3f point = new Vector3f().add(startPoint, new Vector3f(direction.x * width, direction.y * width, direction.z * width));
Vector4f point4f = new Vector4f(point.x, point.y, point.z, 1f);
lightViewMatrix.transform(point4f);
return point4f;
}
/** @return The rotation of the camera represented as a matrix. */
private Matrix4f calculateCameraRotationMatrix()
{
Matrix4f rotation = new Matrix4f();
rotation.rotate((float) Math.toRadians(-cam.getYaw()), new Vector3f(0, 1, 0));
rotation.rotate((float) Math.toRadians(-cam.getPitch()), new Vector3f(1, 0, 0));
return rotation;
}
/** Calculates the width and height of the near and far planes of the
* camera's view frustum. However, this doesn't have to use the "actual" far
* plane of the view frustum. It can use a shortened view frustum if desired
* by bringing the far-plane closer, which would increase shadow resolution
* but means that distant objects wouldn't cast shadows. */
private void calculateWidthsAndHeights()
{
farWidth = (float) (SHADOW_DISTANCE * Math.tan(Math.toRadians(MasterRenderer.FOV)));
nearWidth = (float) (MasterRenderer.NEAR_PLANE
* Math.tan(Math.toRadians(MasterRenderer.FOV)));
farHeight = farWidth / getAspectRatio();
nearHeight = nearWidth / getAspectRatio();
}
/** @return The aspect ratio of the display (width:height ratio). */
private float getAspectRatio()
{ return (float) LiteCraftMain.width / (float) LiteCraftMain.height; }
}

View File

@ -1,112 +0,0 @@
package io.github.hydos.ginger.engine.shadow;
import java.nio.ByteBuffer;
import org.lwjgl.opengl.*;
import com.github.halotroop.litecraft.LiteCraftMain;
/** The frame buffer for the shadow pass. This class sets up the depth texture
* which can be rendered to during the shadow render pass, producing a shadow
* map. */
public class ShadowFrameBuffer
{
private final int WIDTH;
private final int HEIGHT;
private int fbo;
private int shadowMap;
/** Initialises the frame buffer and shadow map of a certain size.
*
* @param width
* - the width of the shadow map in pixels.
* @param height
* - the height of the shadow map in pixels. */
protected ShadowFrameBuffer(int width, int height)
{
this.WIDTH = width;
this.HEIGHT = height;
initialiseFrameBuffer();
}
/** Deletes the frame buffer and shadow map texture when the game closes. */
protected void cleanUp()
{
GL30.glDeleteFramebuffers(fbo);
GL11.glDeleteTextures(shadowMap);
}
/** Binds the frame buffer, setting it as the current render target. */
protected void bindFrameBuffer()
{ bindFrameBuffer(fbo, WIDTH, HEIGHT); }
/** Unbinds the frame buffer, setting the default frame buffer as the current
* render target. */
protected void unbindFrameBuffer()
{
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, 0);
GL11.glViewport(0, 0, LiteCraftMain.width, LiteCraftMain.height);
}
/** @return The ID of the shadow map texture. */
protected int getShadowMap()
{ return shadowMap; }
/** Creates the frame buffer and adds its depth attachment texture. */
private void initialiseFrameBuffer()
{
fbo = createFrameBuffer();
shadowMap = createDepthBufferAttachment(WIDTH, HEIGHT);
unbindFrameBuffer();
}
/** Binds the frame buffer as the current render target.
*
* @param frameBuffer
* - the frame buffer.
* @param width
* - the width of the frame buffer.
* @param height
* - the height of the frame buffer. */
private static void bindFrameBuffer(int frameBuffer, int width, int height)
{
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, frameBuffer);
GL11.glViewport(0, 0, width, height);
}
/** Creates a frame buffer and binds it so that attachments can be added to
* it. The draw buffer is set to none, indicating that there's no colour
* buffer to be rendered to.
*
* @return The newly created frame buffer's ID. */
private static int createFrameBuffer()
{
int frameBuffer = GL30.glGenFramebuffers();
GL30.glBindFramebuffer(GL30.GL_FRAMEBUFFER, frameBuffer);
GL11.glDrawBuffer(GL11.GL_NONE);
GL11.glReadBuffer(GL11.GL_NONE);
return frameBuffer;
}
/** Creates a depth buffer texture attachment.
*
* @param width
* - the width of the texture.
* @param height
* - the height of the texture.
* @return The ID of the depth texture. */
private static int createDepthBufferAttachment(int width, int height)
{
int texture = GL11.glGenTextures();
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL14.GL_DEPTH_COMPONENT16, width, height, 0,
GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, (ByteBuffer) null);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL12.GL_CLAMP_TO_EDGE);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL12.GL_CLAMP_TO_EDGE);
GL32.glFramebufferTexture(GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, texture, 0);
return texture;
}
}

View File

@ -1,86 +0,0 @@
package io.github.hydos.ginger.engine.shadow;
import java.util.*;
import org.joml.Matrix4f;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.elements.objects.Entity;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.MasterRenderer;
import io.github.hydos.ginger.engine.render.models.*;
public class ShadowMapEntityRenderer
{
private Matrix4f projectionViewMatrix;
private ShadowShader shader;
/** @param shader
* - the simple shader program being used for the shadow render
* pass.
* @param projectionViewMatrix
* - the orthographic projection matrix multiplied by the light's
* "view" matrix. */
protected ShadowMapEntityRenderer(ShadowShader shader, Matrix4f projectionViewMatrix)
{
this.shader = shader;
this.projectionViewMatrix = projectionViewMatrix;
}
/** Renders entieis to the shadow map. Each model is first bound and then all
* of the entities using that model are rendered to the shadow map.
*
* @param entities
* - the entities to be rendered to the shadow map. */
protected void render(Map<TexturedModel, List<Entity>> entities)
{
for (TexturedModel model : entities.keySet())
{
RawModel rawModel = model.getRawModel();
bindModel(rawModel);
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, model.getTexture().getTextureID());
if (model.getTexture().isTransparent())
{ MasterRenderer.disableCulling(); }
for (Entity entity : entities.get(model))
{
prepareInstance(entity);
GL11.glDrawElements(GL11.GL_TRIANGLES, rawModel.getVertexCount(),
GL11.GL_UNSIGNED_INT, 0);
}
if (model.getTexture().isTransparent())
{ MasterRenderer.enableCulling(); }
}
GL20.glDisableVertexAttribArray(0);
GL20.glDisableVertexAttribArray(1);
GL30.glBindVertexArray(0);
}
/** Binds a raw model before rendering. Only the attribute 0 is enabled here
* because that is where the positions are stored in the VAO, and only the
* positions are required in the vertex shader.
*
* @param rawModel
* - the model to be bound. */
private void bindModel(RawModel rawModel)
{
GL30.glBindVertexArray(rawModel.getVaoID());
GL20.glEnableVertexAttribArray(0);
GL20.glEnableVertexAttribArray(1);
}
/** Prepares an entity to be rendered. The model matrix is created in the
* usual way and then multiplied with the projection and view matrix (often
* in the past we've done this in the vertex shader) to create the
* mvp-matrix. This is then loaded to the vertex shader as a uniform.
*
* @param entity
* - the entity to be prepared for rendering. */
private void prepareInstance(Entity entity)
{
Matrix4f modelMatrix = Maths.createTransformationMatrix(entity.getPosition(),
entity.getRotX(), entity.getRotY(), entity.getRotZ(), entity.getScale());
Matrix4f mvpMatrix = new Matrix4f().mul(projectionViewMatrix, modelMatrix);
shader.loadMvpMatrix(mvpMatrix);
}
}

View File

@ -1,189 +0,0 @@
package io.github.hydos.ginger.engine.shadow;
import java.lang.Math;
import java.util.*;
import org.joml.*;
import org.lwjgl.opengl.GL11;
import io.github.hydos.ginger.engine.cameras.ThirdPersonCamera;
import io.github.hydos.ginger.engine.elements.objects.*;
import io.github.hydos.ginger.engine.render.models.TexturedModel;
/** This class is in charge of using all of the classes in the shadows package to
* carry out the shadow render pass, i.e. rendering the scene to the shadow map
* texture. This is the only class in the shadows package which needs to be
* referenced from outside the shadows package. */
public class ShadowMapMasterRenderer
{
private static final int SHADOW_MAP_SIZE = 5120;
private ShadowFrameBuffer shadowFbo;
private ShadowShader shader;
private ShadowBox shadowBox;
private Matrix4f projectionMatrix = new Matrix4f();
private Matrix4f lightViewMatrix = new Matrix4f();
private Matrix4f projectionViewMatrix = new Matrix4f();
private Matrix4f offset = createOffset();
private ShadowMapEntityRenderer entityRenderer;
/** Creates instances of the important objects needed for rendering the scene
* to the shadow map. This includes the {@link ShadowBox} which calculates
* the position and size of the "view cuboid", the simple renderer and
* shader program that are used to render objects to the shadow map, and the
* {@link ShadowFrameBuffer} to which the scene is rendered. The size of the
* shadow map is determined here.
*
* @param camera
* - the camera being used in the scene. */
public ShadowMapMasterRenderer(ThirdPersonCamera camera)
{
shader = new ShadowShader();
shadowBox = new ShadowBox(lightViewMatrix, camera);
shadowFbo = new ShadowFrameBuffer(SHADOW_MAP_SIZE, SHADOW_MAP_SIZE);
entityRenderer = new ShadowMapEntityRenderer(shader, projectionViewMatrix);
}
/** Carries out the shadow render pass. This renders the entities to the
* shadow map. First the shadow box is updated to calculate the size and
* position of the "view cuboid". The light direction is assumed to be
* "-lightPosition" which will be fairly accurate assuming that the light is
* very far from the scene. It then prepares to render, renders the entities
* to the shadow map, and finishes rendering.
*
* @param entities
* - the lists of entities to be rendered. Each list is
* associated with the {@link TexturedModel} that all of the
* entities in that list use.
* @param sun
* - the light acting as the sun in the scene. */
public void render(Map<TexturedModel, List<Entity>> entities, Light sun)
{
shadowBox.update();
Vector3f sunPosition = sun.getPosition();
Vector3f lightDirection = new Vector3f(-sunPosition.x, -sunPosition.y, -sunPosition.z);
prepare(lightDirection, shadowBox);
entityRenderer.render(entities);
finish();
}
/** This biased projection-view matrix is used to convert fragments into
* "shadow map space" when rendering the main render pass. It converts a
* world space position into a 2D coordinate on the shadow map. This is
* needed for the second part of shadow mapping.
*
* @return The to-shadow-map-space matrix. */
public Matrix4f getToShadowMapSpaceMatrix()
{ return new Matrix4f().mul(offset, projectionViewMatrix); }
/** Clean up the shader and FBO on closing. */
public void cleanUp()
{
shader.cleanUp();
shadowFbo.cleanUp();
}
/** @return The ID of the shadow map texture. The ID will always stay the
* same, even when the contents of the shadow map texture change
* each frame. */
public int getShadowMap()
{ return shadowFbo.getShadowMap(); }
/** @return The light's "view" matrix. */
protected Matrix4f getLightSpaceTransform()
{ return lightViewMatrix; }
/** Prepare for the shadow render pass. This first updates the dimensions of
* the orthographic "view cuboid" based on the information that was
* calculated in the {@link SHadowBox} class. The light's "view" matrix is
* also calculated based on the light's direction and the center position of
* the "view cuboid" which was also calculated in the {@link ShadowBox}
* class. These two matrices are multiplied together to create the
* projection-view matrix. This matrix determines the size, position, and
* orientation of the "view cuboid" in the world. This method also binds the
* shadows FBO so that everything rendered after this gets rendered to the
* FBO. It also enables depth testing, and clears any data that is in the
* FBOs depth attachment from last frame. The simple shader program is also
* started.
*
* @param lightDirection
* - the direction of the light rays coming from the sun.
* @param box
* - the shadow box, which contains all the info about the
* "view cuboid". */
private void prepare(Vector3f lightDirection, ShadowBox box)
{
updateOrthoProjectionMatrix(box.getWidth(), box.getHeight(), box.getLength());
updateLightViewMatrix(lightDirection, box.getCenter());
projectionViewMatrix.mul(projectionMatrix, lightViewMatrix);
shadowFbo.bindFrameBuffer();
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
shader.start();
}
/** Finish the shadow render pass. Stops the shader and unbinds the shadow
* FBO, so everything rendered after this point is rendered to the screen,
* rather than to the shadow FBO. */
private void finish()
{
shader.stop();
shadowFbo.unbindFrameBuffer();
}
/** Updates the "view" matrix of the light. This creates a view matrix which
* will line up the direction of the "view cuboid" with the direction of the
* light. The light itself has no position, so the "view" matrix is centered
* at the center of the "view cuboid". The created view matrix determines
* where and how the "view cuboid" is positioned in the world. The size of
* the view cuboid, however, is determined by the projection matrix.
*
* @param direction
* - the light direction, and therefore the direction that the
* "view cuboid" should be pointing.
* @param center
* - the center of the "view cuboid" in world space. */
private void updateLightViewMatrix(Vector3f direction, Vector3f center)
{
direction.normalize();
center.negate();
lightViewMatrix.identity();
float pitch = (float) Math.acos(new Vector2f(direction.x, direction.z).length());
lightViewMatrix.rotate(pitch, new Vector3f(1, 0, 0), lightViewMatrix);
float yaw = (float) Math.toDegrees(((float) Math.atan(direction.x / direction.z)));
yaw = direction.z > 0 ? yaw - 180 : yaw;
lightViewMatrix.rotate((float) -Math.toRadians(yaw), new Vector3f(0, 1, 0), lightViewMatrix);
lightViewMatrix.translate(center, lightViewMatrix);
}
/** Creates the orthographic projection matrix. This projection matrix
* basically sets the width, length and height of the "view cuboid", based
* on the values that were calculated in the {@link ShadowBox} class.
*
* @param width
* - shadow box width.
* @param height
* - shadow box height.
* @param length
* - shadow box length. */
private void updateOrthoProjectionMatrix(float width, float height, float length)
{
projectionMatrix.identity();
projectionMatrix.m00(2f / width);
projectionMatrix.m11(2f / height);
projectionMatrix.m22(-2f / length);
projectionMatrix.m33(1);
}
/** Create the offset for part of the conversion to shadow map space. This
* conversion is necessary to convert from one coordinate system to the
* coordinate system that we can use to sample to shadow map.
*
* @return The offset as a matrix (so that it's easy to apply to other matrices). */
private static Matrix4f createOffset()
{
Matrix4f offset = new Matrix4f();
offset.translate(new Vector3f(0.5f, 0.5f, 0.5f));
offset.scale(new Vector3f(0.5f, 0.5f, 0.5f));
return offset;
}
}

View File

@ -1,160 +0,0 @@
package io.github.hydos.ginger.engine.terrain;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.Math;
import javax.imageio.ImageIO;
import org.joml.*;
import io.github.hydos.ginger.engine.math.Maths;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.utils.Loader;
import io.github.hydos.ginger.main.settings.Constants;
public class Terrain
{
private static final float MAX_PIXEL_COLOUR = 256 * 256 * 256;
private float[][] heights;
private float x, z;
private RawModel model;
private TerrainTexturePack texturePack;
private TerrainTexture blendMap;
public Terrain(float gridX, float gridZ, TerrainTexturePack texturePack, TerrainTexture blendMap, String heightMapLocation)
{
this.texturePack = texturePack;
this.blendMap = blendMap;
this.x = gridX * Constants.terrainSize;
this.z = gridZ * Constants.terrainSize;
this.model = generateTerrain(heightMapLocation);
}
public float getHeightOfTerrain(float worldX, float worldZ)
{
float terrainX = worldX - this.x;
float terrainZ = worldZ - this.z;
float gridSquareSize = Constants.terrainSize / ((float) heights.length - 1);
int gridX = (int) Math.floor(terrainX / gridSquareSize);
int gridZ = (int) Math.floor(terrainZ / gridSquareSize);
if (gridX >= heights.length - 1 || gridZ >= heights.length - 1 || gridX < 0 || gridZ < 0)
{ return 0; }
float xCoord = (terrainX % gridSquareSize) / gridSquareSize;
float zCoord = (terrainZ % gridSquareSize) / gridSquareSize;
float answer;
if (xCoord <= (1 - zCoord))
{
answer = Maths
.barryCentric(new Vector3f(0, heights[gridX][gridZ], 0), new Vector3f(1,
heights[gridX + 1][gridZ], 0),
new Vector3f(0,
heights[gridX][gridZ + 1], 1),
new Vector2f(xCoord, zCoord));
}
else
{
answer = Maths
.barryCentric(new Vector3f(1, heights[gridX + 1][gridZ], 0), new Vector3f(1,
heights[gridX + 1][gridZ + 1], 1),
new Vector3f(0,
heights[gridX][gridZ + 1], 1),
new Vector2f(xCoord, zCoord));
}
return answer;
}
public float getX()
{ return x; }
public float getZ()
{ return z; }
public RawModel getModel()
{ return model; }
public TerrainTexturePack getTexturePack()
{ return texturePack; }
public TerrainTexture getBlendMap()
{ return blendMap; }
private RawModel generateTerrain(String heightMap)
{
BufferedImage image = null;
try
{
image = ImageIO.read(Class.class.getResourceAsStream("/textures/terrain/" + heightMap));
}
catch (IOException e)
{
e.printStackTrace();
}
int VERTEX_COUNT = image.getHeight();
heights = new float[VERTEX_COUNT][VERTEX_COUNT];
int count = VERTEX_COUNT * VERTEX_COUNT;
float[] vertices = new float[count * 3];
float[] normals = new float[count * 3];
float[] textureCoords = new float[count * 2];
int[] indices = new int[6 * (VERTEX_COUNT - 1) * (VERTEX_COUNT - 1)];
int vertexPointer = 0;
for (int i = 0; i < VERTEX_COUNT; i++)
{
for (int j = 0; j < VERTEX_COUNT; j++)
{
vertices[vertexPointer * 3] = j / ((float) VERTEX_COUNT - 1) * Constants.terrainSize;
float height = getHeight(j, i, image);
heights[j][i] = height;
vertices[vertexPointer * 3 + 1] = height;
vertices[vertexPointer * 3 + 2] = i / ((float) VERTEX_COUNT - 1) * Constants.terrainSize;
Vector3f normal = calculateNormal(j, i, image);
normals[vertexPointer * 3] = normal.x;
normals[vertexPointer * 3 + 1] = normal.y;
normals[vertexPointer * 3 + 2] = normal.z;
textureCoords[vertexPointer * 2] = j / ((float) VERTEX_COUNT - 1);
textureCoords[vertexPointer * 2 + 1] = i / ((float) VERTEX_COUNT - 1);
vertexPointer++;
}
}
int pointer = 0;
for (int gz = 0; gz < VERTEX_COUNT - 1; gz++)
{
for (int gx = 0; gx < VERTEX_COUNT - 1; gx++)
{
int topLeft = (gz * VERTEX_COUNT) + gx;
int topRight = topLeft + 1;
int bottomLeft = ((gz + 1) * VERTEX_COUNT) + gx;
int bottomRight = bottomLeft + 1;
indices[pointer++] = topLeft;
indices[pointer++] = bottomLeft;
indices[pointer++] = topRight;
indices[pointer++] = topRight;
indices[pointer++] = bottomLeft;
indices[pointer++] = bottomRight;
}
}
return Loader.loadToVAO(vertices, indices, normals, textureCoords);
}
private float getHeight(int x, int z, BufferedImage image)
{
if (x < 0 || x >= image.getHeight() || z < 0 || z >= image.getHeight())
{ return 0; }
float height = image.getRGB(x, z);
height += MAX_PIXEL_COLOUR / 2f;
height /= MAX_PIXEL_COLOUR / 2f;
height *= Constants.terrainMaxHeight;
return height;
}
private Vector3f calculateNormal(int x, int z, BufferedImage image)
{
float heightL = getHeight(x - 1, z, image);
float heightR = getHeight(x + 1, z, image);
float heightD = getHeight(x, z - 1, image);
float heightU = getHeight(x, z + 1, image);
Vector3f normal = new Vector3f(heightL - heightR, 2f, heightD - heightU);
normal.normalize();
return normal;
}
}

View File

@ -1,223 +0,0 @@
package io.github.hydos.ginger.engine.utils;
import java.nio.*;
import java.util.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.*;
import io.github.hydos.ginger.engine.io.Window;
import io.github.hydos.ginger.engine.render.models.RawModel;
import io.github.hydos.ginger.engine.render.texture.*;
import io.github.hydos.ginger.engine.terrain.TerrainTexture;
public class Loader
{
private static List<Integer> vaos = new ArrayList<Integer>();
private static List<Integer> vbos = new ArrayList<Integer>();
public static int loadCubeMap(String[] textureFiles)
{
int texID = GL11.glGenTextures();
GL13.glActiveTexture(GL13.GL_TEXTURE0);
GL11.glBindTexture(GL13.GL_TEXTURE_CUBE_MAP, texID);
for (int i = 0; i < textureFiles.length; i++)
{
// System.out.println("/textures/skybox/" + textureFiles[i]);
Image data = Image.createImage("/textures/skybox/" + textureFiles[i]);
GL11.glTexImage2D(GL13.GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL11.GL_RGBA, data.getWidth(), data.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, data.getImage());
}
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
GL11.glTexParameteri(GL13.GL_TEXTURE_CUBE_MAP, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
vaos.add(texID);
return texID;
}
private static void bindIndicesBuffer(int[] indices)
{
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboID);
IntBuffer buffer = storeDataInIntBuffer(indices);
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
}
public static RawModel loadToVAO(float[] positions, int dimensions)
{
int vaoID = createVAO();
storeDataInAttributeList(0, dimensions, positions);
unbindVAO();
return new RawModel(vaoID, positions.length / dimensions);
}
private static IntBuffer storeDataInIntBuffer(int[] data)
{
IntBuffer buffer = BufferUtils.createIntBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
private static int createVAO()
{
int vaoID = GL30.glGenVertexArrays();
vaos.add(vaoID);
GL30.glBindVertexArray(vaoID);
return vaoID;
}
public static int createEmptyVbo(int floatCount)
{
int vbo = GL15.glGenBuffers();
vbos.add(vbo);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, floatCount * 4, GL15.GL_STREAM_DRAW);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
return vbo;
}
public static void updateVbo(int vbo, float[] data, FloatBuffer buffer)
{
buffer.clear();
buffer.put(data);
buffer.flip();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer.capacity() * 4, GL15.GL_STREAM_DRAW);
GL15.glBufferSubData(GL15.GL_ARRAY_BUFFER, 0, buffer);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
public static void addInstancedAttribute(int vao, int vbo, int att, int dataSize, int instancedDataLength, int offset)
{
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbo);
GL30.glBindVertexArray(vao);
GL20.glVertexAttribPointer(att, dataSize, GL11.GL_FLOAT, false, instancedDataLength * 4, offset * 4);
GL33.glVertexAttribDivisor(att, 1);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
GL30.glBindVertexArray(0);
}
private static void storeDataInAttributeList(int attributeNumber, int coordinateSize, float[] data)
{
int vboID = GL15.glGenBuffers();
vbos.add(vboID);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboID);
FloatBuffer buffer = storeDataInFloatBuffer(data);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
GL20.glVertexAttribPointer(attributeNumber, coordinateSize, GL11.GL_FLOAT, false, 0, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
private static void unbindVAO()
{ GL30.glBindVertexArray(0); }
private static FloatBuffer storeDataInFloatBuffer(float[] data)
{
FloatBuffer buffer = BufferUtils.createFloatBuffer(data.length);
buffer.put(data);
buffer.flip();
return buffer;
}
public static void cleanUp()
{
for (int vao : vaos)
{ GL30.glDeleteVertexArrays(vao); }
for (int vbo : vbos)
{ GL15.glDeleteBuffers(vbo); }
}
public static int loadToVAO(float[] positions, float[] textureCoords)
{
int vaoID = createVAO();
storeDataInAttributeList(0, 2, positions);
storeDataInAttributeList(1, 2, textureCoords);
unbindVAO();
return vaoID;
}
public static RawModel loadToVAO(float[] positions, int[] indices, float[] normals, float[] textureCoords)
{
int vaoID = createVAO();
bindIndicesBuffer(indices);
storeDataInAttributeList(0, 3, positions);
storeDataInAttributeList(1, 2, textureCoords);
storeDataInAttributeList(2, 3, normals);
unbindVAO();
return new RawModel(vaoID, indices.length);
}
public static RawModel loadToVAO(float[] positions, int[] indices, float[] normals, float[] tangents, float[] textureCoords)
{
int vaoID = createVAO();
bindIndicesBuffer(indices);
storeDataInAttributeList(0, 3, positions);
storeDataInAttributeList(1, 2, textureCoords);
storeDataInAttributeList(2, 3, normals);
storeDataInAttributeList(3, 3, tangents);
unbindVAO();
return new RawModel(vaoID, indices.length);
}
public static TerrainTexture loadTerrainTexture(String string)
{ return new TerrainTexture(new ModelTexture("terrain/" + string).getTextureID()); }
public static int loadTexture(String path)
{
int textureID = GL11.glGenTextures();
Image texture = Image.createImage("/textures/" + path);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10241, 9729.0f);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10240, 9729.0f);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, texture.getWidth(), texture.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texture.getImage());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -1f);
if (Window.glContext.GL_EXT_texture_filter_anisotropic)
{//TODO: add option to use or disable
float amount = Math.min(4f, GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, amount);
}
else
System.out.println("anisotropic not supported!");
return textureID;
}
public static int loadTextureDirectly(String path)
{
int textureID = GL11.glGenTextures();
Image texture = Image.createImage(path);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10241, 9729.0f);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10240, 9729.0f);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, texture.getWidth(), texture.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texture.getImage());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -1f);
if (Window.glContext.GL_EXT_texture_filter_anisotropic)
{//TODO: add option to use or disable
float amount = Math.min(4f, GL11.glGetFloat(EXTTextureFilterAnisotropic.GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT));
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, amount);
}
else
System.out.println("anisotropic not supported!");
return textureID;
}
public static int loadFontAtlas(String path)
{
int textureID = GL11.glGenTextures();
Image texture = Image.createImage("/fonts/" + path);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, textureID);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10241, 9729.0f);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, 10240, 9729.0f);
GL11.glTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, texture.getWidth(), texture.getHeight(), 0, GL11.GL_RGBA, GL11.GL_UNSIGNED_BYTE, texture.getImage());
GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
GL30.glGenerateMipmap(GL11.GL_TEXTURE_2D);
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR_MIPMAP_LINEAR);
GL11.glTexParameterf(GL11.GL_TEXTURE_2D, GL14.GL_TEXTURE_LOD_BIAS, -0f);
return textureID;
}
}

View File

@ -1,40 +0,0 @@
package io.github.hydos.ginger.main;
import io.github.hydos.ginger.UI.UIManager;
import io.github.hydos.ginger.UI.enums.UIColourType;
import io.github.hydos.ginger.engine.font.TextMaster;
import io.github.hydos.ginger.engine.obj.ModelLoader;
import io.github.hydos.ginger.engine.obj.normals.NormalMappedObjLoader;
import io.github.hydos.ginger.engine.render.MasterRenderer;
import io.github.hydos.ginger.engine.render.models.*;
import io.github.hydos.ginger.engine.render.texture.ModelTexture;
public class GingerMain
{
public static UIManager manager;
public static void init()
{
TextMaster.init();
manager = new UIManager(UIColourType.dark);
}
public static TexturedModel createTexturedModel(String texturePath, String modelPath)
{
TexturedModel model = ModelLoader.loadModel(modelPath, texturePath);
return model;
}
public static TexturedModel createTexturedModel(String texturePath, String modelPath, String normalMapPath)
{
RawModel model = NormalMappedObjLoader.loadOBJ(modelPath);
TexturedModel texturedModel = new TexturedModel(model, new ModelTexture(texturePath));
return texturedModel;
}
public static void update()
{ manager.update(); }
public static void preRenderScene(MasterRenderer renderer)
{ renderer.renderGui(manager.getBackgroundTexture()); }
}