fix merge conflict
This commit is contained in:
commit
c7a194c0d3
13 changed files with 278 additions and 41251 deletions
2
.gitmodules
vendored
2
.gitmodules
vendored
|
|
@ -1,6 +1,6 @@
|
|||
[submodule "raylib"]
|
||||
path = raylib
|
||||
url = https://github.com/raysan5/raylib
|
||||
url = git@forge.irithice.cc:irithice/raylib-voxel.git
|
||||
[submodule "znoise"]
|
||||
path = znoise
|
||||
url = https://github.com/zig-gamedev/znoise
|
||||
|
|
|
|||
2
raylib
2
raylib
|
|
@ -1 +1 @@
|
|||
Subproject commit a5639bb186f5c5644c1eee02f5954320637cfb02
|
||||
Subproject commit 77e626060d3c5419c539edfa4fe4f268f9015ade
|
||||
BIN
resources/images/ambient_occlusion.png
Normal file
BIN
resources/images/ambient_occlusion.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 74 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.8 KiB |
100
resources/scripts/ambient_occlusion_texture_generator.py
Normal file
100
resources/scripts/ambient_occlusion_texture_generator.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
from PIL import Image, ImageFilter
|
||||
import random
|
||||
import math
|
||||
|
||||
SQUARE_SIZE = 32
|
||||
SQUARES = 2**8
|
||||
ITERATIONS_PER_PIXEL = 1000
|
||||
COORDS = [(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, -1), (0, -1), (1, -1)]
|
||||
|
||||
|
||||
def random_point_on_sphere():
|
||||
theta = random.uniform(0, 2 * math.pi)
|
||||
phi = math.acos(random.uniform(-1, 1))
|
||||
x = math.sin(phi) * math.cos(theta)
|
||||
y = math.sin(phi) * math.sin(theta)
|
||||
z = math.cos(phi)
|
||||
return [x, y, z]
|
||||
|
||||
|
||||
calculated_squares = dict()
|
||||
with Image.new("RGBA", (SQUARE_SIZE*SQUARES, SQUARE_SIZE), "black") as im:
|
||||
px = im.load()
|
||||
|
||||
for square_id in range(SQUARES):
|
||||
print(f"square {square_id}: ", end="")
|
||||
square = square_id
|
||||
|
||||
# if 2 side touching tiles are obscuring, then we can assume the corner is obscuring as well
|
||||
if square & (1 << 6) > 0 and square & (1 << 4) > 0:
|
||||
square = square | (1 << 5)
|
||||
if square & (1 << 4) > 0 and square & (1 << 2) > 0:
|
||||
square = square | (1 << 3)
|
||||
if square & (1 << 2) > 0 and square & (1 << 0) > 0:
|
||||
square = square | (1 << 1)
|
||||
if square & (1 << 0) > 0 and square & (1 << 6) > 0:
|
||||
square = square | (1 << 7)
|
||||
|
||||
# check if we've already done the task in a rotated variation
|
||||
instance_found = False
|
||||
for rotation in range(4): # clockwise rotations by pi/2
|
||||
rotated_square = (square >> (rotation * 2)) | ((square & ((1 << rotation*2)-1)) << 2*(4 - rotation))
|
||||
if rotated_square in calculated_squares:
|
||||
square_id_from = calculated_squares[rotated_square]
|
||||
print(f"already calculated at {square_id_from}")
|
||||
|
||||
box_from = (SQUARE_SIZE*square_id_from, 0, SQUARE_SIZE*(square_id_from+1), SQUARE_SIZE)
|
||||
box_to = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE)
|
||||
region = im.crop(box_from)
|
||||
if rotation == 1:
|
||||
region = region.transpose(Image.Transpose.ROTATE_270)
|
||||
if rotation == 2:
|
||||
region = region.transpose(Image.Transpose.ROTATE_180)
|
||||
if rotation == 3:
|
||||
region = region.transpose(Image.Transpose.ROTATE_90)
|
||||
im.paste(region, box_to)
|
||||
|
||||
instance_found = True
|
||||
break
|
||||
if instance_found:
|
||||
continue
|
||||
|
||||
# actually calculate the occlusion
|
||||
obscured = [i for c, i in enumerate(COORDS) if (square >> c) & 1 == 1]
|
||||
for x in range(SQUARE_SIZE):
|
||||
for y in range(SQUARE_SIZE):
|
||||
point_coord = ((x+0.5)/SQUARE_SIZE-0.5, (y+0.5)/SQUARE_SIZE-0.5, 0)
|
||||
count = 0
|
||||
for i in range(ITERATIONS_PER_PIXEL):
|
||||
point = random_point_on_sphere()
|
||||
point[0] += point_coord[0]
|
||||
point[1] += point_coord[1]
|
||||
rounded_point = (round(point[0]), round(point[1]))
|
||||
if rounded_point in obscured:
|
||||
count += 1
|
||||
result_color = 255-255*count//ITERATIONS_PER_PIXEL
|
||||
px[x+square_id*SQUARE_SIZE, y] = (result_color, result_color, result_color, 255)
|
||||
calculated_squares[square] = square_id
|
||||
|
||||
# smooth it
|
||||
box = (SQUARE_SIZE*square_id, 0, SQUARE_SIZE*(square_id+1), SQUARE_SIZE)
|
||||
region = im.crop(box)
|
||||
region = region.filter(filter=ImageFilter.GaussianBlur(2))
|
||||
im.paste(region, box)
|
||||
|
||||
print(f"calculated")
|
||||
|
||||
print(f"total squares calculated: {len(calculated_squares)}")
|
||||
|
||||
# result_side_length = int(SQUARES**0.5)
|
||||
# with Image.new("RGBA", (SQUARE_SIZE*result_side_length, SQUARE_SIZE*result_side_length), "black") as new_im:
|
||||
# for i in range(result_side_length):
|
||||
# box_from = (SQUARE_SIZE*result_side_length*i, 0, SQUARE_SIZE*result_side_length*(i+1), SQUARE_SIZE)
|
||||
# box_to = (0, SQUARE_SIZE*i, SQUARE_SIZE*result_side_length, SQUARE_SIZE*(i+1))
|
||||
# new_im.paste(im.crop(box_from), box_to)
|
||||
# new_im.show()
|
||||
# new_im.save("../images/ambient_occlusion.png")
|
||||
|
||||
im.show()
|
||||
im.save("../images/ambient_occlusion.png")
|
||||
|
||||
|
|
@ -1,43 +1,69 @@
|
|||
#version 330 core
|
||||
|
||||
uniform sampler2D diffuseMap;
|
||||
uniform sampler2D occlusionMap;
|
||||
uniform vec2 textureTiling;
|
||||
|
||||
in vec2 fragTexCoord;
|
||||
in vec3 fragNormal;
|
||||
in vec2 fragTileTexCoord;
|
||||
flat in int ambientOcclusionSide1;
|
||||
flat in int ambientOcclusionSide2;
|
||||
flat in int ambientOcclusionCorner1;
|
||||
flat in int ambientOcclusionCorner2;
|
||||
flat in int ambientOcclusionCorner3;
|
||||
|
||||
flat in uvec4 occlusionSides;
|
||||
flat in int topLeftObscured;
|
||||
flat in int topRightObscured;
|
||||
flat in int bottomLeftObscured;
|
||||
flat in int bottomRightObscured;
|
||||
flat in int quadHeight;
|
||||
flat in int quadWidth;
|
||||
|
||||
out vec4 outColor;
|
||||
|
||||
// this is a shitty approximation of arcsin(x)/pi that gets the tails right and is reasonably close to the actual arcsin(x)/pi curve.
|
||||
float fakeArcsin(float x) {
|
||||
x = clamp(x, -1.0, 1.0);
|
||||
float ax = abs(x);
|
||||
float sqrtPart = sqrt(1.0 - ax);
|
||||
float result = 0.5 - sqrtPart * (0.5 - 0.06667 * ax);
|
||||
return x < 0.0 ? -result : result;
|
||||
int calculate_ao_square()
|
||||
{
|
||||
ivec2 tileCoord = ivec2(fragTileTexCoord);
|
||||
int ao_square = 0;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && ((occlusionSides.x & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 0;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y == quadHeight - 1 && bottomRightObscured > 0) ao_square |= 1 << 1;
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y != quadHeight - 1 && ((occlusionSides.x & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 1;
|
||||
if(tileCoord.x != quadWidth - 1 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 1;
|
||||
|
||||
if(tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 2;
|
||||
|
||||
if(tileCoord.x == 0 && tileCoord.y == quadHeight - 1 && bottomLeftObscured > 0) ao_square |= 1 << 3;
|
||||
if(tileCoord.x == 0 && tileCoord.y != quadHeight - 1 && ((occlusionSides.y & uint(1 << (tileCoord.y+1))) > uint(0))) ao_square |= 1 << 3;
|
||||
if(tileCoord.x != 0 && tileCoord.y == quadHeight - 1 && ((occlusionSides.w & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 3;
|
||||
|
||||
if(tileCoord.x == 0 && ((occlusionSides.y & uint(1 << tileCoord.y)) > uint(0))) ao_square |= 1 << 4;
|
||||
|
||||
if(tileCoord.x == 0 && tileCoord.y == 0 && topRightObscured > 0) ao_square |= 1 << 5;
|
||||
if(tileCoord.x == 0 && tileCoord.y != 0 && ((occlusionSides.y & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 5;
|
||||
if(tileCoord.x != 0 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x-1))) > uint(0))) ao_square |= 1 << 5;
|
||||
|
||||
if(tileCoord.y == 0 && ((occlusionSides.z & uint(1 << tileCoord.x)) > uint(0))) ao_square |= 1 << 6;
|
||||
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y == 0 && topLeftObscured > 0) ao_square |= 1 << 7;
|
||||
if(tileCoord.x == quadWidth - 1 && tileCoord.y != 0 && ((occlusionSides.x & uint(1 << (tileCoord.y-1))) > uint(0))) ao_square |= 1 << 7;
|
||||
if(tileCoord.x != quadWidth - 1 && tileCoord.y == 0 && ((occlusionSides.z & uint(1 << (tileCoord.x+1))) > uint(0))) ao_square |= 1 << 7;
|
||||
|
||||
return ao_square;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texCoord = (floor(fragTexCoord*textureTiling) + fract(fragTileTexCoord)) / textureTiling;
|
||||
|
||||
int ao_square = calculate_ao_square();
|
||||
|
||||
outColor = texture(diffuseMap, texCoord);
|
||||
|
||||
ivec2 floorFragTileTexCoord = ivec2(fragTileTexCoord);
|
||||
|
||||
if(fragTileTexCoord.x < 1 && (((ambientOcclusionSide1 >> floorFragTileTexCoord.y) & 1) == 1)) outColor *= 0.5 + fakeArcsin(fragTileTexCoord.x);
|
||||
|
||||
// if(fragTileTexCoord.x < 0.125 && fragTileTexCoord.x < fract(fragTileTexCoord.y) && fragTileTexCoord.x + fract(fragTileTexCoord.y) < 1.0 && ((ambientOcclusionSide1 >> floorFragTileTexCoord.y) & 1) == 1) outColor *= 0.5;
|
||||
|
||||
//if((fragTileTexCoord.x < 0.25 || fragTileTexCoord.x > quadWidth-0.25) && (((ambientOcclusionSide1 >> floorFragTileTexCoord.y) & 1) == 1)) outColor *= 0.5;
|
||||
//if((fragTileTexCoord.y < 0.25 || fragTileTexCoord.y > quadHeight-0.25) && (((ambientOcclusionSide2 >> floorFragTileTexCoord.y) & 1) == 1)) outColor *= 0.5;
|
||||
outColor *= texture(occlusionMap, (vec2(ao_square, 0)+fract(fragTileTexCoord))/vec2(256, 1));
|
||||
|
||||
outColor.a = 1;
|
||||
|
||||
//uint bit = uint(fragTileTexCoord * 32);
|
||||
//outColor.g = (((uint(quadWidth) >> bit) & uint(1)) == uint(1)) ?
|
||||
// ((bit % uint(2) == uint(0)) ? 1.0 : 0.8):
|
||||
// ((bit % uint(2) == uint(0)) ? 0.0 : 0.2);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,17 +4,18 @@ in vec3 vertexPosition;
|
|||
in vec2 vertexTexCoord;
|
||||
in vec3 vertexNormal;
|
||||
in vec2 vertexTileTexCoord;
|
||||
in vec4 vertexMetadata1;
|
||||
in uvec4 vertexMetadata1;
|
||||
in uvec4 vertexOcclusionSides;
|
||||
|
||||
out vec2 fragTexCoord;
|
||||
out vec3 fragNormal;
|
||||
out vec2 fragTileTexCoord;
|
||||
|
||||
flat out int ambientOcclusionSide1;
|
||||
flat out int ambientOcclusionSide2;
|
||||
flat out int ambientOcclusionCorner1;
|
||||
flat out int ambientOcclusionCorner2;
|
||||
flat out int ambientOcclusionCorner3;
|
||||
flat out uvec4 occlusionSides;
|
||||
flat out int topLeftObscured;
|
||||
flat out int topRightObscured;
|
||||
flat out int bottomLeftObscured;
|
||||
flat out int bottomRightObscured;
|
||||
flat out int quadHeight;
|
||||
flat out int quadWidth;
|
||||
|
||||
|
|
@ -24,16 +25,15 @@ void main() {
|
|||
fragTexCoord = vertexTexCoord;
|
||||
fragTileTexCoord = vertexTileTexCoord;
|
||||
fragNormal = vertexNormal;
|
||||
occlusionSides = vertexOcclusionSides;
|
||||
gl_Position = mvp*vec4(vertexPosition, 1.0);
|
||||
|
||||
// metadata 1 parsing
|
||||
ambientOcclusionSide1 = floatBitsToInt(vertexMetadata1.x);
|
||||
ambientOcclusionSide2 = floatBitsToInt(vertexMetadata1.y);
|
||||
int metadata1Z = floatBitsToInt(vertexMetadata1.z);
|
||||
int metadata1W = floatBitsToInt(vertexMetadata1.w);
|
||||
ambientOcclusionCorner1 = (metadata1Z & 0x1) >> 0; // Take 0th bit.
|
||||
ambientOcclusionCorner2 = (metadata1Z & 0x2) >> 1; // Take 1st bit.
|
||||
ambientOcclusionCorner3 = (metadata1Z & 0x4) >> 2; // Take 2nd bit.
|
||||
quadHeight = (metadata1Z & 0x1f8) >> 3; // Take 3rd-8th bits.
|
||||
quadWidth = (metadata1Z & 0x7e00) >> 9; // Take 9th-14th bits.
|
||||
int metadata1W = int(vertexMetadata1.x);
|
||||
topLeftObscured = (metadata1W & 0x1); // Take 0th bit.
|
||||
topRightObscured = (metadata1W & 0x2) >> 1; // Take 1st bits.
|
||||
bottomLeftObscured = (metadata1W & 0x4) >> 2; // Take 2nd bits.
|
||||
bottomRightObscured = (metadata1W & 0x8) >> 3; // Take 3rd bits.
|
||||
quadHeight = (metadata1W & 0x3f0) >> 4; // Take 4rd-9th bits.
|
||||
quadWidth = (metadata1W & 0xfc00) >> 10; // Take 10th-16th bits.
|
||||
}
|
||||
|
|
|
|||
40465
rmodels.tmpzig
40465
rmodels.tmpzig
File diff suppressed because it is too large
Load diff
|
|
@ -1,675 +0,0 @@
|
|||
/**********************************************************************************************
|
||||
* This file contains modified pieces of code from the Raylib library.
|
||||
* Original license follows below.
|
||||
*
|
||||
* LICENSE: zlib/libpng
|
||||
*
|
||||
* Copyright (c) 2014-2025 Ramon Santamaria (@raysan5)
|
||||
*
|
||||
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||
* will the authors be held liable for any damages arising from the use of this software.
|
||||
*
|
||||
* Permission is granted to anyone to use this software for any purpose, including commercial
|
||||
* applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
*
|
||||
* 1. The origin of this software must not be misrepresented; you must not claim that you
|
||||
* wrote the original software. If you use this software in a product, an acknowledgment
|
||||
* in the product documentation would be appreciated but is not required.
|
||||
*
|
||||
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented
|
||||
* as being the original software.
|
||||
*
|
||||
* 3. This notice may not be removed or altered from any source distribution.
|
||||
**********************************************************************************************/
|
||||
|
||||
#include "raylib.h"
|
||||
#include "rlgl.h"
|
||||
#include "raymath.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHUNK_MAX_MESH_VERTEX_BUFFERS 5
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION 0
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD 1
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL 2
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD 3
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1 4
|
||||
|
||||
#define CHUNK_MAX_MATERIAL_MAPS 12
|
||||
#define CHUNK_MAX_SHADER_LOCATIONS 32
|
||||
|
||||
typedef enum {
|
||||
CHUNK_SHADER_LOC_VERTEX_POSITION = 0, // Shader location: vertex attribute: position
|
||||
CHUNK_SHADER_LOC_VERTEX_TEXCOORD, // Shader location: vertex attribute: texcoord
|
||||
CHUNK_SHADER_LOC_VERTEX_NORMAL, // Shader location: vertex attribute: normal
|
||||
CHUNK_SHADER_LOC_VERTEX_TILETEXCOORD, // Shader location: vertex attribute: tiletexcoord
|
||||
CHUNK_SHADER_LOC_VERTEX_METADATA1, // Shader location: vertex attribute: metadata1
|
||||
CHUNK_SHADER_LOC_MATRIX_MVP, // Shader location: matrix uniform: model-view-projection
|
||||
CHUNK_SHADER_LOC_MATRIX_VIEW, // Shader location: matrix uniform: view (camera transform)
|
||||
CHUNK_SHADER_LOC_MATRIX_PROJECTION, // Shader location: matrix uniform: projection
|
||||
CHUNK_SHADER_LOC_MATRIX_MODEL, // Shader location: matrix uniform: model (transform)
|
||||
CHUNK_SHADER_LOC_MATRIX_NORMAL, // Shader location: matrix uniform: normal
|
||||
CHUNK_SHADER_LOC_VECTOR_VIEW, // Shader location: vector uniform: view
|
||||
CHUNK_SHADER_LOC_COLOR_DIFFUSE, // Shader location: vector uniform: diffuse color
|
||||
CHUNK_SHADER_LOC_COLOR_SPECULAR, // Shader location: vector uniform: specular color
|
||||
CHUNK_SHADER_LOC_COLOR_AMBIENT, // Shader location: vector uniform: ambient color
|
||||
CHUNK_SHADER_LOC_MAP_ALBEDO, // Shader location: sampler2d texture: albedo (same as: CHUNK_SHADER_LOC_MAP_DIFFUSE)
|
||||
CHUNK_SHADER_LOC_MAP_METALNESS, // Shader location: sampler2d texture: metalness (same as: CHUNK_SHADER_LOC_MAP_SPECULAR)
|
||||
CHUNK_SHADER_LOC_MAP_NORMAL, // Shader location: sampler2d texture: normal
|
||||
CHUNK_SHADER_LOC_MAP_ROUGHNESS, // Shader location: sampler2d texture: roughness
|
||||
CHUNK_SHADER_LOC_MAP_OCCLUSION, // Shader location: sampler2d texture: occlusion
|
||||
CHUNK_SHADER_LOC_MAP_EMISSION, // Shader location: sampler2d texture: emission
|
||||
CHUNK_SHADER_LOC_MAP_HEIGHT, // Shader location: sampler2d texture: height
|
||||
CHUNK_SHADER_LOC_MAP_CUBEMAP, // Shader location: samplerCube texture: cubemap
|
||||
CHUNK_SHADER_LOC_MAP_IRRADIANCE, // Shader location: samplerCube texture: irradiance
|
||||
CHUNK_SHADER_LOC_MAP_PREFILTER, // Shader location: samplerCube texture: prefilter
|
||||
CHUNK_SHADER_LOC_MAP_BRDF // Shader location: sampler2d texture: brdf
|
||||
} chunkShaderLocationIndex;
|
||||
|
||||
#define CHUNK_SHADER_LOC_MAP_DIFFUSE CHUNK_SHADER_LOC_MAP_ALBEDO
|
||||
#define CHUNK_SHADER_LOC_MAP_SPECULAR CHUNK_SHADER_LOC_MAP_METALNESS
|
||||
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_NAME_POSITION "vertexPosition" // Bound by default to shader location: CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD "vertexTexCoord" // Bound by default to shader location: CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_NAME_NORMAL "vertexNormal" // Bound by default to shader location: CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TILETEXCOORD "vertexTileTexCoord" // Bound by default to shader location: CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD
|
||||
#define CHUNK_DEFAULT_SHADER_ATTRIB_NAME_METADATA1 "vertexMetadata1" // Bound by default to shader location: CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_MVP "mvp" // model-view-projection matrix
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_VIEW "matView" // view matrix
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION "matProjection" // projection matrix
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_MODEL "matModel" // model matrix
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_NORMAL "matNormal" // normal matrix (transpose(inverse(matModelView)))
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_COLOR "colDiffuse" // color diffuse (base tint color, multiplied by texture color)
|
||||
#define CHUNK_DEFAULT_SHADER_UNIFORM_NAME_BONE_MATRICES "boneMatrices" // bone matrices
|
||||
#define CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0 "texture0" // texture0 (texture slot active 0)
|
||||
#define CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1 "texture1" // texture1 (texture slot active 1)
|
||||
#define CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2 "texture2" // texture2 (texture slot active 2)
|
||||
|
||||
typedef struct ChunkMesh {
|
||||
int vertexCount; // Number of vertices stored in arrays
|
||||
int triangleCount; // Number of triangles stored (indexed or not)
|
||||
|
||||
// Vertex attributes data
|
||||
float *vertices; // Vertex position (XYZ - 3 components per vertex) (shader-location = 0)
|
||||
float *texcoords; // Vertex texture coordinates (UV - 2 components per vertex) (shader-location = 1)
|
||||
float *normals; // Vertex normals (XYZ - 3 components per vertex) (shader-location = 2)
|
||||
float *tiletexcoords; // Vertex tile tex coordinates (UV - 2 components per vertex) (shader-location = 3)
|
||||
float *metadata1; // Vertex metadata 1 (ABCD - 4 components per vertex) (shader-location = 4)
|
||||
|
||||
// OpenGL identifiers
|
||||
unsigned int vaoId; // OpenGL Vertex Array Object id
|
||||
unsigned int *vboId; // OpenGL Vertex Buffer Objects id (default vertex data)
|
||||
} ChunkMesh;
|
||||
|
||||
// Model, meshes, materials and animation data
|
||||
typedef struct ChunkModel {
|
||||
Matrix transform; // Local transform matrix
|
||||
|
||||
int meshCount; // Number of meshes
|
||||
int materialCount; // Number of materials
|
||||
ChunkMesh *meshes; // Meshes array
|
||||
Material *materials; // Materials array
|
||||
int *meshMaterial; // Mesh material number
|
||||
|
||||
// Animation data
|
||||
int boneCount; // Number of bones
|
||||
BoneInfo *bones; // Bones information (skeleton)
|
||||
Transform *bindPose; // Bones base transformation (pose)
|
||||
} ChunkModel;
|
||||
|
||||
RLAPI void UploadChunkMesh(ChunkMesh *mesh, bool dynamic); // Upload mesh vertex data in GPU and provide VAO/VBO ids
|
||||
RLAPI ChunkModel LoadChunkModelFromMesh(ChunkMesh mesh); // Load model from generated mesh (default material)
|
||||
RLAPI void UnloadChunkModel(ChunkModel model); // Unload model (including meshes) from memory (RAM and/or VRAM)
|
||||
RLAPI void UnloadChunkMesh(ChunkMesh mesh); // Unload mesh data from CPU and GPU
|
||||
RLAPI void DrawChunkModel(ChunkModel model, Vector3 position, float scale, Color tint); // Draw a model (with texture if set)
|
||||
RLAPI void DrawChunkModelEx(ChunkModel model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint); // Draw a model with extended parameters
|
||||
RLAPI void DrawChunkMesh(ChunkMesh mesh, Material material, Matrix transform); // Draw a 3d mesh with material and transform
|
||||
RLAPI Shader LoadChunkShader(const char *vsFileName, const char *fsFileName); // Load shader from files and bind default locations
|
||||
RLAPI Shader LoadChunkShaderFromMemory(const char *vsCode, const char *fsCode); // Load shader from code strings and bind default locations
|
||||
|
||||
RLAPI unsigned int chunkLoadShaderCode(const char *vsCode, const char *fsCode); // Load shader from code strings
|
||||
RLAPI unsigned int chunkLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId); // Load custom shader program
|
||||
|
||||
// Upload vertex data into a VAO (if supported) and VBO
|
||||
void UploadChunkMesh(ChunkMesh *mesh, bool dynamic) {
|
||||
if (mesh->vaoId > 0)
|
||||
{
|
||||
// Check if mesh has already been loaded in GPU
|
||||
printf("CHUNK VAO: [ID %i] Trying to re-load an already loaded mesh\n", mesh->vaoId);
|
||||
return;
|
||||
}
|
||||
|
||||
mesh->vboId = (unsigned int *)RL_CALLOC(CHUNK_MAX_MESH_VERTEX_BUFFERS, sizeof(unsigned int));
|
||||
|
||||
mesh->vaoId = 0; // Vertex Array Object
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = 0;
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = 0;
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = 0;
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD] = 0;
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1] = 0;
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
mesh->vaoId = rlLoadVertexArray();
|
||||
rlEnableVertexArray(mesh->vaoId);
|
||||
|
||||
// NOTE: Vertex attributes must be uploaded considering default locations points and available vertex data
|
||||
|
||||
// Enable vertex attributes: position (shader-location = 0)
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION] = rlLoadVertexBuffer(mesh->vertices, mesh->vertexCount*3*sizeof(float), dynamic);
|
||||
rlSetVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, 3, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION);
|
||||
|
||||
// Enable vertex attributes: texcoords (shader-location = 1)
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD] = rlLoadVertexBuffer(mesh->texcoords, mesh->vertexCount*2*sizeof(float), dynamic);
|
||||
rlSetVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, 2, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD);
|
||||
|
||||
// Enable vertex attributes: normals (shader-location = 2)
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL] = rlLoadVertexBuffer(mesh->normals, mesh->vertexCount*3*sizeof(float), dynamic);
|
||||
rlSetVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, 3, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL);
|
||||
|
||||
// Enable vertex attribute: tiletexcoord (shader-location = 3)
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD] = rlLoadVertexBuffer(mesh->tiletexcoords, mesh->vertexCount*2*sizeof(float), dynamic);
|
||||
rlSetVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD, 2, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD);
|
||||
|
||||
// Enable vertex attribute: metadata1 (shader-location = 4)
|
||||
mesh->vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1] = rlLoadVertexBuffer(mesh->metadata1, mesh->vertexCount*4*sizeof(float), dynamic);
|
||||
rlSetVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1, 4, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1);
|
||||
|
||||
if (mesh->vaoId > 0) printf("CHUNK VAO: [ID %i] Mesh uploaded successfully to VRAM (GPU)\n", mesh->vaoId);
|
||||
else printf("CHUNK VBO: Mesh uploaded successfully to VRAM (GPU)");
|
||||
|
||||
rlDisableVertexArray();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Load model from generated mesh
|
||||
// WARNING: A shallow copy of mesh is generated, passed by value,
|
||||
// as long as struct contains pointers to data and some values, we get a copy
|
||||
// of mesh pointing to same data as original version... be careful!
|
||||
ChunkModel LoadChunkModelFromMesh(ChunkMesh mesh)
|
||||
{
|
||||
ChunkModel model = { 0 };
|
||||
|
||||
model.transform = MatrixIdentity();
|
||||
|
||||
model.meshCount = 1;
|
||||
model.meshes = (ChunkMesh *)RL_CALLOC(model.meshCount, sizeof(ChunkMesh));
|
||||
model.meshes[0] = mesh;
|
||||
|
||||
model.materialCount = 1;
|
||||
model.materials = (Material *)RL_CALLOC(model.materialCount, sizeof(Material));
|
||||
model.materials[0] = LoadMaterialDefault();
|
||||
|
||||
model.meshMaterial = (int *)RL_CALLOC(model.meshCount, sizeof(int));
|
||||
model.meshMaterial[0] = 0; // First material index
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
// Unload model (meshes/materials) from memory (RAM and/or VRAM)
|
||||
// NOTE: This function takes care of all model elements, for a detailed control
|
||||
// over them, use UnloadMesh() and UnloadMaterial()
|
||||
void UnloadChunkModel(ChunkModel model)
|
||||
{
|
||||
// Unload meshes
|
||||
for (int i = 0; i < model.meshCount; i++) UnloadChunkMesh(model.meshes[i]);
|
||||
|
||||
// Unload materials maps
|
||||
// NOTE: As the user could be sharing shaders and textures between models,
|
||||
// we don't unload the material but just free its maps,
|
||||
// the user is responsible for freeing models shaders and textures
|
||||
for (int i = 0; i < model.materialCount; i++) RL_FREE(model.materials[i].maps);
|
||||
|
||||
// Unload arrays
|
||||
RL_FREE(model.meshes);
|
||||
RL_FREE(model.materials);
|
||||
RL_FREE(model.meshMaterial);
|
||||
|
||||
TRACELOG(LOG_INFO, "CHUNK MODEL: Unloaded model (and meshes) from RAM and VRAM");
|
||||
}
|
||||
|
||||
// Unload mesh from memory (RAM and VRAM)
|
||||
void UnloadChunkMesh(ChunkMesh mesh)
|
||||
{
|
||||
// Unload rlgl mesh vboId data
|
||||
rlUnloadVertexArray(mesh.vaoId);
|
||||
|
||||
if (mesh.vboId != NULL) for (int i = 0; i < CHUNK_MAX_MESH_VERTEX_BUFFERS; i++) rlUnloadVertexBuffer(mesh.vboId[i]);
|
||||
RL_FREE(mesh.vboId);
|
||||
|
||||
RL_FREE(mesh.vertices);
|
||||
RL_FREE(mesh.texcoords);
|
||||
RL_FREE(mesh.normals);
|
||||
RL_FREE(mesh.tiletexcoords);
|
||||
}
|
||||
|
||||
// Draw a model (with texture if set)
|
||||
void DrawChunkModel(ChunkModel model, Vector3 position, float scale, Color tint)
|
||||
{
|
||||
Vector3 vScale = { scale, scale, scale };
|
||||
Vector3 rotationAxis = { 0.0f, 1.0f, 0.0f };
|
||||
|
||||
DrawChunkModelEx(model, position, rotationAxis, 0.0f, vScale, tint);
|
||||
}
|
||||
|
||||
// Draw a model with extended parameters
|
||||
void DrawChunkModelEx(ChunkModel model, Vector3 position, Vector3 rotationAxis, float rotationAngle, Vector3 scale, Color tint)
|
||||
{
|
||||
// Calculate transformation matrix from function parameters
|
||||
// Get transform matrix (rotation -> scale -> translation)
|
||||
Matrix matScale = MatrixScale(scale.x, scale.y, scale.z);
|
||||
Matrix matRotation = MatrixRotate(rotationAxis, rotationAngle*DEG2RAD);
|
||||
Matrix matTranslation = MatrixTranslate(position.x, position.y, position.z);
|
||||
|
||||
Matrix matTransform = MatrixMultiply(MatrixMultiply(matScale, matRotation), matTranslation);
|
||||
|
||||
// Combine model transformation matrix (model.transform) with matrix generated by function parameters (matTransform)
|
||||
model.transform = MatrixMultiply(model.transform, matTransform);
|
||||
|
||||
for (int i = 0; i < model.meshCount; i++)
|
||||
{
|
||||
Color color = model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color;
|
||||
|
||||
Color colorTint = WHITE;
|
||||
colorTint.r = (unsigned char)(((int)color.r*(int)tint.r)/255);
|
||||
colorTint.g = (unsigned char)(((int)color.g*(int)tint.g)/255);
|
||||
colorTint.b = (unsigned char)(((int)color.b*(int)tint.b)/255);
|
||||
colorTint.a = (unsigned char)(((int)color.a*(int)tint.a)/255);
|
||||
|
||||
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = colorTint;
|
||||
DrawChunkMesh(model.meshes[i], model.materials[model.meshMaterial[i]], model.transform);
|
||||
model.materials[model.meshMaterial[i]].maps[MATERIAL_MAP_DIFFUSE].color = color;
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a 3d mesh with material and transform
|
||||
void DrawChunkMesh(ChunkMesh mesh, Material material, Matrix transform)
|
||||
{
|
||||
#if defined(GRAPHICS_API_OPENGL_11)
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_NORMAL_ARRAY 0x8075
|
||||
#define GL_COLOR_ARRAY 0x8076
|
||||
#define GL_TEXTURE_COORD_ARRAY 0x8078
|
||||
|
||||
rlEnableTexture(material.maps[MATERIAL_MAP_DIFFUSE].texture.id);
|
||||
|
||||
rlEnableStatePointer(GL_VERTEX_ARRAY, mesh.vertices);
|
||||
rlEnableStatePointer(GL_TEXTURE_COORD_ARRAY, mesh.texcoords);
|
||||
rlEnableStatePointer(GL_NORMAL_ARRAY, mesh.normals);
|
||||
rlEnableStatePointer(GL_COLOR_ARRAY, mesh.colors);
|
||||
|
||||
rlPushMatrix();
|
||||
rlMultMatrixf(MatrixToFloat(transform));
|
||||
rlColor4ub(material.maps[MATERIAL_MAP_DIFFUSE].color.r,
|
||||
material.maps[MATERIAL_MAP_DIFFUSE].color.g,
|
||||
material.maps[MATERIAL_MAP_DIFFUSE].color.b,
|
||||
material.maps[MATERIAL_MAP_DIFFUSE].color.a);
|
||||
|
||||
if (mesh.indices != NULL) rlDrawVertexArrayElements(0, mesh.triangleCount*3, mesh.indices);
|
||||
else rlDrawVertexArray(0, mesh.vertexCount);
|
||||
rlPopMatrix();
|
||||
|
||||
rlDisableStatePointer(GL_VERTEX_ARRAY);
|
||||
rlDisableStatePointer(GL_TEXTURE_COORD_ARRAY);
|
||||
rlDisableStatePointer(GL_NORMAL_ARRAY);
|
||||
rlDisableStatePointer(GL_COLOR_ARRAY);
|
||||
|
||||
rlDisableTexture();
|
||||
#endif
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
// Bind shader program
|
||||
rlEnableShader(material.shader.id);
|
||||
|
||||
// Send required data to shader (matrices, values)
|
||||
//-----------------------------------------------------
|
||||
// Upload to shader material.colDiffuse
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_COLOR_DIFFUSE] != -1)
|
||||
{
|
||||
float values[4] = {
|
||||
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.r/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.g/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.b/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_DIFFUSE].color.a/255.0f
|
||||
};
|
||||
|
||||
rlSetUniform(material.shader.locs[CHUNK_SHADER_LOC_COLOR_DIFFUSE], values, SHADER_UNIFORM_VEC4, 1);
|
||||
}
|
||||
|
||||
// Upload to shader material.colSpecular (if location available)
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_COLOR_SPECULAR] != -1)
|
||||
{
|
||||
float values[4] = {
|
||||
(float)material.maps[MATERIAL_MAP_SPECULAR].color.r/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_SPECULAR].color.g/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_SPECULAR].color.b/255.0f,
|
||||
(float)material.maps[MATERIAL_MAP_SPECULAR].color.a/255.0f
|
||||
};
|
||||
|
||||
rlSetUniform(material.shader.locs[CHUNK_SHADER_LOC_COLOR_SPECULAR], values, SHADER_UNIFORM_VEC4, 1);
|
||||
}
|
||||
|
||||
// Get a copy of current matrices to work with,
|
||||
// just in case stereo render is required, and we need to modify them
|
||||
// NOTE: At this point the modelview matrix just contains the view matrix (camera)
|
||||
// That's because BeginMode3D() sets it and there is no model-drawing function
|
||||
// that modifies it, all use rlPushMatrix() and rlPopMatrix()
|
||||
Matrix matModel = MatrixIdentity();
|
||||
Matrix matView = rlGetMatrixModelview();
|
||||
Matrix matModelView = MatrixIdentity();
|
||||
Matrix matProjection = rlGetMatrixProjection();
|
||||
|
||||
// Upload view and projection matrices (if locations available)
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_MATRIX_VIEW] != -1) rlSetUniformMatrix(material.shader.locs[CHUNK_SHADER_LOC_MATRIX_VIEW], matView);
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_MATRIX_PROJECTION] != -1) rlSetUniformMatrix(material.shader.locs[CHUNK_SHADER_LOC_MATRIX_PROJECTION], matProjection);
|
||||
|
||||
// Accumulate several model transformations:
|
||||
// transform: model transformation provided (includes DrawModel() params combined with model.transform)
|
||||
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
|
||||
matModel = MatrixMultiply(transform, rlGetMatrixTransform());
|
||||
|
||||
// Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[CHUNK_SHADER_LOC_MATRIX_MODEL], matModel);
|
||||
|
||||
// Get model-view matrix
|
||||
matModelView = MatrixMultiply(matModel, matView);
|
||||
|
||||
// Upload model normal matrix (if locations available)
|
||||
if (material.shader.locs[CHUNK_SHADER_LOC_MATRIX_NORMAL] != -1) rlSetUniformMatrix(material.shader.locs[CHUNK_SHADER_LOC_MATRIX_NORMAL], MatrixTranspose(MatrixInvert(matModel)));
|
||||
//-----------------------------------------------------
|
||||
|
||||
// Bind active texture maps (if available)
|
||||
for (int i = 0; i < CHUNK_MAX_MATERIAL_MAPS; i++)
|
||||
{
|
||||
if (material.maps[i].texture.id > 0)
|
||||
{
|
||||
// Select current shader texture slot
|
||||
rlActiveTextureSlot(i);
|
||||
|
||||
// Enable texture for active slot
|
||||
if ((i == MATERIAL_MAP_IRRADIANCE) ||
|
||||
(i == MATERIAL_MAP_PREFILTER) ||
|
||||
(i == MATERIAL_MAP_CUBEMAP)) rlEnableTextureCubemap(material.maps[i].texture.id);
|
||||
else rlEnableTexture(material.maps[i].texture.id);
|
||||
|
||||
rlSetUniform(material.shader.locs[CHUNK_SHADER_LOC_MAP_DIFFUSE + i], &i, SHADER_UNIFORM_INT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Try binding vertex array objects (VAO) or use VBOs if not possible
|
||||
// WARNING: UploadMesh() enables all vertex attributes available in mesh and sets default attribute values
|
||||
// for shader expected vertex attributes that are not provided by the mesh (i.e. colors)
|
||||
// This could be a dangerous approach because different meshes with different shaders can enable/disable some attributes
|
||||
if (!rlEnableVertexArray(mesh.vaoId))
|
||||
{
|
||||
// Bind mesh VBO data: vertex position (shader-location = 0)
|
||||
rlEnableVertexBuffer(mesh.vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION]);
|
||||
rlSetVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_POSITION], 3, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_POSITION]);
|
||||
|
||||
// Bind mesh VBO data: vertex texcoords (shader-location = 1)
|
||||
rlEnableVertexBuffer(mesh.vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD]);
|
||||
rlSetVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_TEXCOORD], 2, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_TEXCOORD]);
|
||||
|
||||
// Bind mesh VBO data: vertex normal (shader-location = 2)
|
||||
rlEnableVertexBuffer(mesh.vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL]);
|
||||
rlSetVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_NORMAL], 3, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_NORMAL]);
|
||||
|
||||
// Bind mesh VBO data: vertex tiletexcoords (shader-location = 3)
|
||||
rlEnableVertexBuffer(mesh.vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD]);
|
||||
rlSetVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_TILETEXCOORD], 2, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_TILETEXCOORD]);
|
||||
|
||||
// Bind mesh VBO data: vertex metadata1 (shader-location = 4)
|
||||
rlEnableVertexBuffer(mesh.vboId[CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1]);
|
||||
rlSetVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_METADATA1], 4, RL_FLOAT, 0, 0, 0);
|
||||
rlEnableVertexAttribute(material.shader.locs[CHUNK_SHADER_LOC_VERTEX_METADATA1]);
|
||||
}
|
||||
|
||||
int eyeCount = 1;
|
||||
if (rlIsStereoRenderEnabled()) eyeCount = 2;
|
||||
|
||||
for (int eye = 0; eye < eyeCount; eye++)
|
||||
{
|
||||
// Calculate model-view-projection matrix (MVP)
|
||||
Matrix matModelViewProjection = MatrixIdentity();
|
||||
if (eyeCount == 1) matModelViewProjection = MatrixMultiply(matModelView, matProjection);
|
||||
else
|
||||
{
|
||||
// Setup current eye viewport (half screen width)
|
||||
rlViewport(eye*rlGetFramebufferWidth()/2, 0, rlGetFramebufferWidth()/2, rlGetFramebufferHeight());
|
||||
matModelViewProjection = MatrixMultiply(MatrixMultiply(matModelView, rlGetMatrixViewOffsetStereo(eye)), rlGetMatrixProjectionStereo(eye));
|
||||
}
|
||||
|
||||
// Send combined model-view-projection matrix to shader
|
||||
rlSetUniformMatrix(material.shader.locs[CHUNK_SHADER_LOC_MATRIX_MVP], matModelViewProjection);
|
||||
|
||||
// Draw mesh
|
||||
rlDrawVertexArray(0, mesh.vertexCount);
|
||||
}
|
||||
|
||||
// Unbind all bound texture maps
|
||||
for (int i = 0; i < CHUNK_MAX_MATERIAL_MAPS; i++)
|
||||
{
|
||||
if (material.maps[i].texture.id > 0)
|
||||
{
|
||||
// Select current shader texture slot
|
||||
rlActiveTextureSlot(i);
|
||||
|
||||
// Disable texture for active slot
|
||||
if ((i == MATERIAL_MAP_IRRADIANCE) ||
|
||||
(i == MATERIAL_MAP_PREFILTER) ||
|
||||
(i == MATERIAL_MAP_CUBEMAP)) rlDisableTextureCubemap();
|
||||
else rlDisableTexture();
|
||||
}
|
||||
}
|
||||
|
||||
// Disable all possible vertex array objects (or VBOs)
|
||||
rlDisableVertexArray();
|
||||
rlDisableVertexBuffer();
|
||||
rlDisableVertexBufferElement();
|
||||
|
||||
// Disable shader program
|
||||
rlDisableShader();
|
||||
|
||||
// Restore rlgl internal modelview and projection matrices
|
||||
rlSetMatrixModelview(matView);
|
||||
rlSetMatrixProjection(matProjection);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Load shader from files and bind default locations
|
||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||
Shader LoadChunkShader(const char *vsFileName, const char *fsFileName)
|
||||
{
|
||||
Shader shader = { 0 };
|
||||
|
||||
char *vShaderStr = NULL;
|
||||
char *fShaderStr = NULL;
|
||||
|
||||
if (vsFileName != NULL) vShaderStr = LoadFileText(vsFileName);
|
||||
if (fsFileName != NULL) fShaderStr = LoadFileText(fsFileName);
|
||||
|
||||
if ((vShaderStr == NULL) && (fShaderStr == NULL)) printf("CHUNK SHADER: Shader files provided are not valid, using default shader\n");
|
||||
|
||||
shader = LoadChunkShaderFromMemory(vShaderStr, fShaderStr);
|
||||
|
||||
UnloadFileText(vShaderStr);
|
||||
UnloadFileText(fShaderStr);
|
||||
|
||||
printf("CHUNK SHADER: Shader loaded successfully from shader files\n");
|
||||
return shader;
|
||||
}
|
||||
|
||||
// Load shader from code strings and bind default locations
|
||||
Shader LoadChunkShaderFromMemory(const char *vsCode, const char *fsCode)
|
||||
{
|
||||
Shader shader = { 0 };
|
||||
|
||||
shader.id = rlLoadShaderCode(vsCode, fsCode);
|
||||
|
||||
if (shader.id == rlGetShaderIdDefault()) shader.locs = rlGetShaderLocsDefault();
|
||||
else if (shader.id > 0)
|
||||
{
|
||||
// After custom shader loading, we TRY to set default location names
|
||||
// Default shader attribute locations have been binded before linking:
|
||||
// vertex position location = 0
|
||||
// vertex texcoord location = 1
|
||||
// vertex normal location = 2
|
||||
// vertex tiletexcoord location = 3
|
||||
// vertex metadata1 location = 4
|
||||
|
||||
// NOTE: If any location is not found, loc point becomes -1
|
||||
|
||||
shader.locs = (int *)RL_CALLOC(CHUNK_MAX_SHADER_LOCATIONS, sizeof(int));
|
||||
|
||||
// All locations reset to -1 (no location)
|
||||
for (int i = 0; i < CHUNK_MAX_SHADER_LOCATIONS; i++) shader.locs[i] = -1;
|
||||
|
||||
// Get handles to GLSL input attribute locations
|
||||
shader.locs[CHUNK_SHADER_LOC_VERTEX_POSITION] = rlGetLocationAttrib(shader.id, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
|
||||
shader.locs[CHUNK_SHADER_LOC_VERTEX_TEXCOORD] = rlGetLocationAttrib(shader.id, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
|
||||
shader.locs[CHUNK_SHADER_LOC_VERTEX_NORMAL] = rlGetLocationAttrib(shader.id, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
|
||||
shader.locs[CHUNK_SHADER_LOC_VERTEX_TILETEXCOORD] = rlGetLocationAttrib(shader.id, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TILETEXCOORD);
|
||||
shader.locs[CHUNK_SHADER_LOC_VERTEX_METADATA1] = rlGetLocationAttrib(shader.id, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_METADATA1);
|
||||
|
||||
// Get handles to GLSL uniform locations (vertex shader)
|
||||
shader.locs[CHUNK_SHADER_LOC_MATRIX_MVP] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_MVP);
|
||||
shader.locs[CHUNK_SHADER_LOC_MATRIX_VIEW] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_VIEW);
|
||||
shader.locs[CHUNK_SHADER_LOC_MATRIX_PROJECTION] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_PROJECTION);
|
||||
shader.locs[CHUNK_SHADER_LOC_MATRIX_MODEL] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_MODEL);
|
||||
shader.locs[CHUNK_SHADER_LOC_MATRIX_NORMAL] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_NORMAL);
|
||||
|
||||
// Get handles to GLSL uniform locations (fragment shader)
|
||||
shader.locs[CHUNK_SHADER_LOC_COLOR_DIFFUSE] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_UNIFORM_NAME_COLOR);
|
||||
shader.locs[CHUNK_SHADER_LOC_MAP_DIFFUSE] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE0); // SHADER_LOC_MAP_ALBEDO
|
||||
shader.locs[CHUNK_SHADER_LOC_MAP_SPECULAR] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE1); // SHADER_LOC_MAP_METALNESS
|
||||
shader.locs[CHUNK_SHADER_LOC_MAP_NORMAL] = rlGetLocationUniform(shader.id, CHUNK_DEFAULT_SHADER_SAMPLER2D_NAME_TEXTURE2);
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
#ifdef RLGL_IMPLEMENTATION
|
||||
|
||||
// Load custom shader strings and return program id
|
||||
unsigned int chunkLoadShaderProgram(unsigned int vShaderId, unsigned int fShaderId)
|
||||
{
|
||||
unsigned int program = 0;
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
GLint success = 0;
|
||||
program = glCreateProgram();
|
||||
|
||||
glAttachShader(program, vShaderId);
|
||||
glAttachShader(program, fShaderId);
|
||||
|
||||
// NOTE: Default attribute shader locations must be Bound before linking
|
||||
glBindAttribLocation(program, CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_POSITION, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_POSITION);
|
||||
glBindAttribLocation(program, CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TEXCOORD, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TEXCOORD);
|
||||
glBindAttribLocation(program, CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_NORMAL, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_NORMAL);
|
||||
glBindAttribLocation(program, CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_TILETEXCOORD, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_TILETEXCOORD);
|
||||
glBindAttribLocation(program, CHUNK_DEFAULT_SHADER_ATTRIB_LOCATION_METADATA1, CHUNK_DEFAULT_SHADER_ATTRIB_NAME_METADATA1);
|
||||
|
||||
// NOTE: If some attrib name is no found on the shader, it locations becomes -1
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
// NOTE: All uniform variables are intitialised to 0 when a program links
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||
|
||||
if (success == GL_FALSE)
|
||||
{
|
||||
printf("SHADER: [ID %i] Failed to link shader program\n", program);
|
||||
|
||||
int maxLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
if (maxLength > 0)
|
||||
{
|
||||
int length = 0;
|
||||
char *log = (char *)RL_CALLOC(maxLength, sizeof(char));
|
||||
glGetProgramInfoLog(program, maxLength, &length, log);
|
||||
printf("SHADER: [ID %i] Link error: %s\n", program, log);
|
||||
RL_FREE(log);
|
||||
}
|
||||
|
||||
glDeleteProgram(program);
|
||||
|
||||
program = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the size of compiled shader program (not available on OpenGL ES 2.0)
|
||||
// NOTE: If GL_LINK_STATUS is GL_FALSE, program binary length is zero
|
||||
//GLint binarySize = 0;
|
||||
//glGetProgramiv(id, GL_PROGRAM_BINARY_LENGTH, &binarySize);
|
||||
|
||||
printf(RL_LOG_INFO, "SHADER: [ID %i] Program shader loaded successfully\n", program);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Load shader from code strings
|
||||
// NOTE: If shader string is NULL, using default vertex/fragment shaders
|
||||
unsigned int chunkLoadShaderCode(const char *vsCode, const char *fsCode)
|
||||
{
|
||||
unsigned int id = 0;
|
||||
|
||||
#if defined(GRAPHICS_API_OPENGL_33) || defined(GRAPHICS_API_OPENGL_ES2)
|
||||
unsigned int vertexShaderId = 0;
|
||||
unsigned int fragmentShaderId = 0;
|
||||
|
||||
// Compile vertex shader (if provided)
|
||||
// NOTE: If not vertex shader is provided, use default one
|
||||
if (vsCode != NULL) vertexShaderId = rlCompileShader(vsCode, GL_VERTEX_SHADER);
|
||||
else {
|
||||
printf("vertex shader is null!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Compile fragment shader (if provided)
|
||||
// NOTE: If not vertex shader is provided, use default one
|
||||
if (fsCode != NULL) fragmentShaderId = rlCompileShader(fsCode, GL_FRAGMENT_SHADER);
|
||||
else {
|
||||
printf("fragment shader is null!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((vertexShaderId > 0) && (fragmentShaderId > 0))
|
||||
{
|
||||
// One of or both shader are new, we need to compile a new shader program
|
||||
id = chunkLoadShaderProgram(vertexShaderId, fragmentShaderId);
|
||||
|
||||
// WARNING: Shader program linkage could fail and returned id is 0
|
||||
if (id > 0) glDetachShader(id, vertexShaderId);
|
||||
glDeleteShader(vertexShaderId);
|
||||
|
||||
// WARNING: Shader program linkage could fail and returned id is 0
|
||||
if (id > 0) glDetachShader(id, fragmentShaderId);
|
||||
glDeleteShader(fragmentShaderId);
|
||||
|
||||
// In case shader program loading failed
|
||||
if (id == 0)
|
||||
{
|
||||
printf("failed to load custom shaders!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return id;
|
||||
}
|
||||
#endif // RLGL_IMPLEMENTATION
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
pub const raylib = @cImport({
|
||||
@cInclude("raylib_extension.h");
|
||||
@cInclude("raylib.h");
|
||||
@cInclude("rlgl.h");
|
||||
@cInclude("raymath.h");
|
||||
@cInclude("rchunks_extension.h");
|
||||
});
|
||||
|
||||
pub const v3 = struct {
|
||||
|
|
@ -30,6 +33,9 @@ pub const v3 = struct {
|
|||
pub inline fn nor(a: raylib.Vector3) raylib.Vector3 {
|
||||
return raylib.Vector3Normalize(a);
|
||||
}
|
||||
pub inline fn dot(a: raylib.Vector3, b: raylib.Vector3) f32 {
|
||||
return raylib.Vector3DotProduct(a, b);
|
||||
}
|
||||
pub inline fn cross(a: raylib.Vector3, b: raylib.Vector3) raylib.Vector3 {
|
||||
return raylib.Vector3CrossProduct(a, b);
|
||||
}
|
||||
|
|
|
|||
44
src/main.zig
44
src/main.zig
|
|
@ -64,23 +64,19 @@ pub fn main() !void {
|
|||
defer raylib.UnloadTexture(texture);
|
||||
raylib.UnloadImage(tiles);
|
||||
|
||||
const ambient_occlusion_image = raylib.LoadImage("resources/images/ambient_occlusion.png");
|
||||
const ambient_occlusion_texture = raylib.LoadTextureFromImage(ambient_occlusion_image);
|
||||
defer raylib.UnloadTexture(ambient_occlusion_texture);
|
||||
raylib.UnloadImage(ambient_occlusion_image);
|
||||
|
||||
const shader = raylib.LoadChunkShader("resources/shaders/tiling.vs", "resources/shaders/tiling.fs");
|
||||
defer raylib.UnloadShader(shader);
|
||||
//std.debug.print("shader id: {}\n", .{shader.id});
|
||||
//std.debug.print("shader attrib position loc: {}\n", .{raylib.GetShaderLocationAttrib(shader, "vertexPosition")});
|
||||
//std.debug.print("shader attrib texcoord loc: {}\n", .{raylib.GetShaderLocationAttrib(shader, "vertexTexCoord")});
|
||||
//std.debug.print("shader attrib normal loc: {}\n", .{raylib.GetShaderLocationAttrib(shader, "vertexNormal")});
|
||||
//std.debug.print("shader attrib tiletexcoord loc: {}\n", .{raylib.GetShaderLocationAttrib(shader, "vertexTileTexCoord")});
|
||||
//std.debug.print("shader attrib metadata1 loc: {}\n", .{raylib.GetShaderLocationAttrib(shader, "vertexMetadata1")});
|
||||
//for (0..32) |i|{
|
||||
// std.debug.print("shader loc {}: {}\n", .{i, shader.locs[i]});
|
||||
//}
|
||||
raylib.SetShaderValue(shader, raylib.GetShaderLocation(shader, "textureTiling"), &.{ @as(f32, @floatFromInt(tile_columns)), @as(f32, @floatFromInt(tile_rows)) }, raylib.SHADER_UNIFORM_VEC2);
|
||||
|
||||
var chunk = try chunks.Chunk.init(a7r);
|
||||
defer chunk.deinit();
|
||||
|
||||
const height_generator = znoise.FnlGenerator{ .seed = 413445 };
|
||||
// const height_generator = znoise.FnlGenerator{ .seed = 413445 };
|
||||
const tile_type_generator = znoise.FnlGenerator{ .seed = 4435, .frequency = 0.1 };
|
||||
for (0..32) |raw_x| for (0..32) |raw_y| for (0..32) |raw_z| {
|
||||
const x: u5 = @intCast(raw_x);
|
||||
|
|
@ -89,9 +85,10 @@ pub fn main() !void {
|
|||
const xf: f32 = @floatFromInt(raw_x);
|
||||
const yf: f32 = @floatFromInt(raw_y);
|
||||
const zf: f32 = @floatFromInt(raw_z);
|
||||
const height: f32 = (height_generator.noise2(xf, zf) + 1) * 16 + @as(f32, if(x > 24) 4.0 else 0.0) + @as(f32, if(z < 8) 4.0 else 0.0);
|
||||
const tile_type: u32 = if (tile_type_generator.noise3(xf, yf, zf) > 0) 1 else 2;
|
||||
if (height >= yf) chunk.setTile(x, y, z, tile_type);
|
||||
const tile_type: u32 = if (tile_type_generator.noise3(xf, yf, zf) > 0) 2 else 2;
|
||||
// const height: f32 = (height_generator.noise2(xf, zf) + 1) * 16 + @as(f32, if(x > 24) 4.0 else 0.0) + @as(f32, if(z < 8) 4.0 else 0.0);
|
||||
// if (height >= yf) chunk.setTile(x, y, z, tile_type);
|
||||
if((xf-16)*(xf-16)+(yf-16)*(yf-16)+(zf-16)*(zf-16) < 16*16) chunk.setTile(x, y, z, tile_type);
|
||||
};
|
||||
|
||||
if (benchmark_chunk_meshing) {
|
||||
|
|
@ -113,6 +110,13 @@ pub fn main() !void {
|
|||
model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE].texture = texture;
|
||||
model.materials[0].shader = shader;
|
||||
|
||||
model.materials[0].shader.locs[raylib.SHADER_LOC_MAP_DIFFUSE+1] = raylib.GetShaderLocation(shader, "occlusionMap");
|
||||
raylib.SetShaderValueTexture(shader, model.materials[0].shader.locs[raylib.SHADER_LOC_MAP_DIFFUSE+1], ambient_occlusion_texture); model.materials[0].maps[raylib.MATERIAL_MAP_DIFFUSE+1].texture = ambient_occlusion_texture;
|
||||
|
||||
// for (0..32) |i|{
|
||||
// std.debug.print("shader loc {}: {}\n", .{i, shader.locs[i]});
|
||||
// }
|
||||
|
||||
while (!raylib.WindowShouldClose()) {
|
||||
raylib.ClearBackground(raylib.BLACK);
|
||||
|
||||
|
|
@ -133,10 +137,17 @@ pub fn main() !void {
|
|||
moveCamera(&camera, v3.scl(v3.nor(movement), speed));
|
||||
|
||||
const delta = raylib.GetMouseDelta();
|
||||
// on the first mouse movement, for some reason mouse delta is completely insane, so we just ignore too large deltas
|
||||
// on the first mouse movement, for some reason mouse delta is way too large, so we just ignore too large deltas
|
||||
if(delta.x < 1000 and delta.y < 1000 and delta.x > -1000 and delta.y > -1000){
|
||||
camera.target = v3.add(camera.position, v3.rotate(v3.sub(camera.target, camera.position), camera.up, -0.005 * delta.x));
|
||||
camera.target = v3.add(camera.position, v3.rotate(v3.sub(camera.target, camera.position), right, -0.005 * delta.y));
|
||||
var direction = v3.sub(camera.target, camera.position);
|
||||
direction = v3.rotate(direction, camera.up, -0.005 * delta.x);
|
||||
const tmp_direction = direction;
|
||||
direction = v3.rotate(direction, right, -0.005 * delta.y);
|
||||
if(tmp_direction.x*direction.x+tmp_direction.z*direction.z > 0){
|
||||
camera.target = v3.add(camera.position, direction);
|
||||
} else {
|
||||
camera.target = v3.add(camera.position, tmp_direction);
|
||||
}
|
||||
}
|
||||
|
||||
raylib.BeginDrawing();
|
||||
|
|
@ -150,6 +161,7 @@ pub fn main() !void {
|
|||
raylib.BeginShaderMode(shader);
|
||||
defer raylib.EndShaderMode();
|
||||
|
||||
raylib.SetShaderValueTexture(shader, raylib.GetShaderLocation(shader, "ambientOcclusionTexture"), ambient_occlusion_texture);
|
||||
raylib.DrawChunkModel(model, model_position, 0.5, raylib.WHITE);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ const raylib = raylib_helper.raylib;
|
|||
const v3 = raylib_helper.v3;
|
||||
const A7r = std.mem.Allocator;
|
||||
const comptimePrint = std.fmt.comptimePrint;
|
||||
|
||||
const VERTICES_BLOCK_SIZE = 2 * 3 * 3;
|
||||
const TEXCOORDS_BLOCK_SIZE = 2 * 2 * 3;
|
||||
|
||||
const X_DIRECTION = 0;
|
||||
const Y_DIRECTION = 1;
|
||||
const Z_DIRECTION = 2;
|
||||
|
|
@ -19,6 +21,8 @@ const RawQuad = struct {
|
|||
normal: raylib.Vector3,
|
||||
width: f32,
|
||||
height: f32,
|
||||
flip_x: bool,
|
||||
flip_y: bool,
|
||||
|
||||
top_obscuring_pattern: u32,
|
||||
left_obscuring_pattern: u32,
|
||||
|
|
@ -32,15 +36,16 @@ const RawQuad = struct {
|
|||
|
||||
// Quad shader metadata. Has to be 128 bytes in size.
|
||||
const Metadata1 = packed struct {
|
||||
ambient_occlusion_1: u32,
|
||||
ambient_occlusion_2: u32,
|
||||
ambient_occlusion_corner1: bool,
|
||||
ambient_occlusion_corner2: bool,
|
||||
ambient_occlusion_corner3: bool,
|
||||
top_left_obscured: bool,
|
||||
top_right_obscured: bool,
|
||||
bottom_right_obscured: bool,
|
||||
bottom_left_obscured: bool,
|
||||
quad_height: u6,
|
||||
quad_width: u6,
|
||||
unused: u17 = 0,
|
||||
unused: u16 = 0,
|
||||
unused_2: u32 = 0,
|
||||
unused_3: u32 = 0,
|
||||
unused_4: u32 = 0,
|
||||
};
|
||||
|
||||
comptime {
|
||||
|
|
@ -93,7 +98,7 @@ pub const Chunk = struct {
|
|||
}
|
||||
|
||||
// Create a raw quad with specified parameters and surface, accounting for dimension and sign. Surface is the block ID.
|
||||
fn pack_raw_quad(
|
||||
fn packRawQuad(
|
||||
x: f32,
|
||||
y_start: usize, y_end: usize,
|
||||
z_start: usize, z_end: usize,
|
||||
|
|
@ -104,6 +109,10 @@ pub const Chunk = struct {
|
|||
y_plus_obscuring_pattern: u32,
|
||||
z_minus_obscuring_pattern: u32,
|
||||
z_plus_obscuring_pattern: u32,
|
||||
y_minus_z_minus_obscured: bool,
|
||||
y_minus_z_plus_obscured: bool,
|
||||
y_plus_z_plus_obscured: bool,
|
||||
y_plus_z_minus_obscured: bool,
|
||||
) RawQuad {
|
||||
const ymin: f32 = @as(f32, @floatFromInt(y_start)) - 0.5;
|
||||
const ymax: f32 = @as(f32, @floatFromInt(y_end)) - 0.5;
|
||||
|
|
@ -113,6 +122,7 @@ pub const Chunk = struct {
|
|||
const yright: f32 = if (sign == 1) ymax else ymin;
|
||||
const zleft: f32 = if (sign == 1) zmin else zmax;
|
||||
const zright: f32 = if (sign == 1) zmax else zmin;
|
||||
|
||||
var raw_quad: RawQuad = undefined;
|
||||
switch (dimension) {
|
||||
X_DIRECTION => {
|
||||
|
|
@ -125,15 +135,17 @@ pub const Chunk = struct {
|
|||
.normal = v3.new(sign, 0, 0),
|
||||
.width = zmax - zmin,
|
||||
.height = ymax - ymin,
|
||||
.flip_x = sign == -1,
|
||||
.flip_y = false,
|
||||
|
||||
.top_obscuring_pattern = z_plus_obscuring_pattern,
|
||||
.top_obscuring_pattern = y_plus_obscuring_pattern,
|
||||
.left_obscuring_pattern = z_minus_obscuring_pattern,
|
||||
.right_obscuring_pattern = y_plus_obscuring_pattern,
|
||||
.right_obscuring_pattern = z_plus_obscuring_pattern,
|
||||
.bottom_obscuring_pattern = y_minus_obscuring_pattern,
|
||||
.top_left_obscured = false,
|
||||
.top_right_obscured = false,
|
||||
.bottom_right_obscured = false,
|
||||
.bottom_left_obscured = false,
|
||||
.top_left_obscured = y_plus_z_minus_obscured,
|
||||
.top_right_obscured = y_plus_z_plus_obscured,
|
||||
.bottom_right_obscured = y_minus_z_plus_obscured,
|
||||
.bottom_left_obscured = y_minus_z_minus_obscured,
|
||||
};
|
||||
},
|
||||
Y_DIRECTION => {
|
||||
|
|
@ -146,15 +158,17 @@ pub const Chunk = struct {
|
|||
.normal = v3.new(0, 0, sign),
|
||||
.height = zmax - zmin,
|
||||
.width = ymax - ymin,
|
||||
.flip_x = sign == 1,
|
||||
.flip_y = false,
|
||||
|
||||
.top_obscuring_pattern = 0,
|
||||
.left_obscuring_pattern = 0,
|
||||
.right_obscuring_pattern = 0,
|
||||
.bottom_obscuring_pattern = 0,
|
||||
.top_left_obscured = false,
|
||||
.top_right_obscured = false,
|
||||
.bottom_right_obscured = false,
|
||||
.bottom_left_obscured = false,
|
||||
.top_obscuring_pattern = z_plus_obscuring_pattern,
|
||||
.left_obscuring_pattern = y_minus_obscuring_pattern,
|
||||
.right_obscuring_pattern = y_plus_obscuring_pattern,
|
||||
.bottom_obscuring_pattern = z_minus_obscuring_pattern,
|
||||
.top_left_obscured = y_minus_z_plus_obscured,
|
||||
.top_right_obscured = y_plus_z_plus_obscured,
|
||||
.bottom_right_obscured = y_plus_z_minus_obscured,
|
||||
.bottom_left_obscured = y_minus_z_minus_obscured,
|
||||
};
|
||||
},
|
||||
Z_DIRECTION => {
|
||||
|
|
@ -167,15 +181,17 @@ pub const Chunk = struct {
|
|||
.normal = v3.new(0, sign, 0),
|
||||
.width = zmax - zmin,
|
||||
.height = ymax - ymin,
|
||||
.flip_x = sign == 1,
|
||||
.flip_y = true,
|
||||
|
||||
.top_obscuring_pattern = 0,
|
||||
.left_obscuring_pattern = 0,
|
||||
.right_obscuring_pattern = 0,
|
||||
.bottom_obscuring_pattern = 0,
|
||||
.top_left_obscured = false,
|
||||
.top_right_obscured = false,
|
||||
.bottom_right_obscured = false,
|
||||
.bottom_left_obscured = false,
|
||||
.top_obscuring_pattern = y_plus_obscuring_pattern,
|
||||
.left_obscuring_pattern = z_minus_obscuring_pattern,
|
||||
.right_obscuring_pattern = z_plus_obscuring_pattern,
|
||||
.bottom_obscuring_pattern = y_minus_obscuring_pattern,
|
||||
.top_left_obscured = y_plus_z_minus_obscured,
|
||||
.top_right_obscured = y_plus_z_plus_obscured,
|
||||
.bottom_right_obscured = y_minus_z_plus_obscured,
|
||||
.bottom_left_obscured = y_minus_z_minus_obscured,
|
||||
};
|
||||
},
|
||||
else => unreachable,
|
||||
|
|
@ -256,8 +272,19 @@ pub const Chunk = struct {
|
|||
if (chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), z, dimension) != 0) y_plus_obscuring_pattern |= 1;
|
||||
}
|
||||
}
|
||||
// std.debug.print("{}\n", .{z_minus_obscuring_pattern});
|
||||
const raw_quad = pack_raw_quad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, dimension, surface, y_minus_obscuring_pattern, y_plus_obscuring_pattern, z_minus_obscuring_pattern, z_plus_obscuring_pattern);
|
||||
var y_minus_z_minus_obscured = false;
|
||||
var y_minus_z_plus_obscured = false;
|
||||
var y_plus_z_plus_obscured = false;
|
||||
var y_plus_z_minus_obscured = false;
|
||||
if(x != (if (sign == 1) 31 else 0) and y_start != 0 and z_start != 0)
|
||||
y_minus_z_minus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start-1), @intCast(z_start-1), dimension) != 0;
|
||||
if(x != (if (sign == 1) 31 else 0) and y_start != 0 and z_end != 32)
|
||||
y_minus_z_plus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_start-1), @intCast(z_end), dimension) != 0;
|
||||
if(x != (if (sign == 1) 31 else 0) and y_end != 32 and z_end != 32)
|
||||
y_plus_z_plus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), @intCast(z_end), dimension) != 0;
|
||||
if(x != (if (sign == 1) 31 else 0) and y_end != 32 and z_start != 0)
|
||||
y_plus_z_minus_obscured = chunk.getTileRawShifted(if (sign == 1) x+1 else x-1, @intCast(y_end), @intCast(z_start-1), dimension) != 0;
|
||||
const raw_quad = packRawQuad(@floatFromInt(raw_x), y_start, y_end, z_start, z_end, sign, dimension, surface, y_minus_obscuring_pattern, y_plus_obscuring_pattern, z_minus_obscuring_pattern, z_plus_obscuring_pattern, y_minus_z_minus_obscured, y_minus_z_plus_obscured, y_plus_z_plus_obscured, y_plus_z_minus_obscured);
|
||||
try raw_quads.append(raw_quad);
|
||||
};
|
||||
}
|
||||
|
|
@ -273,7 +300,8 @@ pub const Chunk = struct {
|
|||
const texcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
||||
const tiletexcoords: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 2)));
|
||||
const normals: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 3)));
|
||||
const metadata1_packed: [*]f32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 4)));
|
||||
const metadata1_packed: [*]u32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 4)));
|
||||
const occlusion_sides: [*]u32 = @ptrCast(@alignCast(raylib.MemAlloc(arr_size * 4)));
|
||||
|
||||
for (raw_quads.items, 0..) |raw_quad, i| {
|
||||
if (raw_quad.tile <= 0) continue; // air tile, no texture
|
||||
|
|
@ -296,8 +324,10 @@ pub const Chunk = struct {
|
|||
const vertex_corners = .{ raw_quad.top_left, raw_quad.bottom_left, raw_quad.top_right, raw_quad.bottom_right, raw_quad.top_right, raw_quad.bottom_left };
|
||||
const texcoords_x = .{ left_uv, left_uv, right_uv, right_uv, right_uv, left_uv };
|
||||
const texcoords_y = .{ top_uv, bottom_uv } ** 3;
|
||||
const tiletexcoords_x = .{ 0.0, 0.0, raw_quad.width, raw_quad.width, raw_quad.width, 0.0 };
|
||||
const tiletexcoords_y = .{ 0.0, raw_quad.height } ** 3;
|
||||
const tiletexcoords_x = if(raw_quad.flip_x)
|
||||
.{raw_quad.width, raw_quad.width, 0.0, 0.0, 0.0, raw_quad.width} else
|
||||
.{ 0.0, 0.0, raw_quad.width, raw_quad.width, raw_quad.width, 0.0 };
|
||||
const tiletexcoords_y = if(raw_quad.flip_y) .{ raw_quad.height, 0.0 } ** 3 else .{ 0.0, raw_quad.height } ** 3;
|
||||
|
||||
inline for (0..6) |corner_id| {
|
||||
vertices[VERTICES_BLOCK_SIZE * i + corner_id * 3 + 0] = vertex_corners[corner_id].x;
|
||||
|
|
@ -310,35 +340,27 @@ pub const Chunk = struct {
|
|||
}
|
||||
|
||||
// Store metadata into OpenGL buffers.
|
||||
for (0..3) |j| {
|
||||
for (0..6) |j| {
|
||||
const metadata1 = Metadata1{
|
||||
.ambient_occlusion_1 = raw_quad.left_obscuring_pattern,
|
||||
.ambient_occlusion_2 = raw_quad.right_obscuring_pattern,
|
||||
.ambient_occlusion_corner1 = raw_quad.top_left_obscured,
|
||||
.ambient_occlusion_corner2 = raw_quad.bottom_left_obscured,
|
||||
.ambient_occlusion_corner3 = raw_quad.top_right_obscured,
|
||||
.top_left_obscured = raw_quad.top_left_obscured,
|
||||
.top_right_obscured = raw_quad.top_right_obscured,
|
||||
.bottom_left_obscured = raw_quad.bottom_left_obscured,
|
||||
.bottom_right_obscured = raw_quad.bottom_right_obscured,
|
||||
.quad_height = @intFromFloat(raw_quad.height),
|
||||
.quad_width = @intFromFloat(raw_quad.width),
|
||||
};
|
||||
const metadata1_baked: [4]f32 = @bitCast(metadata1);
|
||||
const metadata1_baked: [4]u32 = @bitCast(metadata1);
|
||||
for (0..4) |k| {
|
||||
metadata1_packed[24 * i + 4 * j + k] = @bitCast(@as(f32, metadata1_baked[k]));
|
||||
metadata1_packed[24 * i + 4 * j + k] = metadata1_baked[k];
|
||||
}
|
||||
}
|
||||
for (3..6) |j| {
|
||||
const metadata1 = Metadata1{
|
||||
.ambient_occlusion_1 = raw_quad.right_obscuring_pattern,
|
||||
.ambient_occlusion_2 = raw_quad.bottom_obscuring_pattern,
|
||||
.ambient_occlusion_corner1 = raw_quad.bottom_right_obscured,
|
||||
.ambient_occlusion_corner2 = raw_quad.top_right_obscured,
|
||||
.ambient_occlusion_corner3 = raw_quad.bottom_left_obscured,
|
||||
.quad_height = @intFromFloat(raw_quad.height),
|
||||
.quad_width = @intFromFloat(raw_quad.width),
|
||||
};
|
||||
const metadata1_baked: [4]f32 = @bitCast(metadata1);
|
||||
for (0..4) |k| {
|
||||
metadata1_packed[24 * i + 4 * j + k] = @bitCast(@as(f32, metadata1_baked[k]));
|
||||
}
|
||||
|
||||
// Store ambient occlusion sides into OpenGL buffers.
|
||||
for (0..6) |j| {
|
||||
occlusion_sides[24 * i + 4 * j + 0] = raw_quad.left_obscuring_pattern;
|
||||
occlusion_sides[24 * i + 4 * j + 1] = raw_quad.right_obscuring_pattern;
|
||||
occlusion_sides[24 * i + 4 * j + 2] = raw_quad.top_obscuring_pattern;
|
||||
occlusion_sides[24 * i + 4 * j + 3] = raw_quad.bottom_obscuring_pattern;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,6 +374,7 @@ pub const Chunk = struct {
|
|||
.tiletexcoords = tiletexcoords,
|
||||
.normals = normals,
|
||||
.metadata1 = metadata1_packed,
|
||||
.occlusion_sides = occlusion_sides,
|
||||
|
||||
.vaoId = 0,
|
||||
.vboId = null,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue