From 9b06763cfbf831318b03e6dd241fe501a71873f6 Mon Sep 17 00:00:00 2001 From: maelstrom Date: Tue, 19 Nov 2024 12:46:43 +0100 Subject: [PATCH] Studs --- assets/shaders/phong.fs | 14 +++++++++-- assets/shaders/phong.vs | 42 +++++++++++++++++++++++++++++++ assets/textures/studs.png | Bin 0 -> 6031 bytes src/rendering/defaultmeshes.cpp | 2 +- src/rendering/renderer.cpp | 14 ++++++++++- src/rendering/texture.cpp | 4 +-- src/rendering/texture.h | 2 +- src/rendering/texture3d.cpp | 43 ++++++++++++++++++++++++++++++++ src/rendering/texture3d.h | 13 ++++++++++ 9 files changed, 127 insertions(+), 7 deletions(-) create mode 100644 assets/textures/studs.png create mode 100644 src/rendering/texture3d.cpp create mode 100644 src/rendering/texture3d.h diff --git a/assets/shaders/phong.fs b/assets/shaders/phong.fs index d1debe6..66a2099 100644 --- a/assets/shaders/phong.fs +++ b/assets/shaders/phong.fs @@ -29,11 +29,19 @@ struct PointLight { float quadratic; }; +const int FaceRight = 0; +const int FaceTop = 1; +const int FaceBack = 2; +const int FaceLeft = 3; +const int FaceBottom = 4; +const int FaceFront = 5; + // I/O in vec3 vPos; in vec3 vNormal; in vec2 vTexCoords; +flat in int vSurfaceZ; out vec4 FragColor; @@ -44,6 +52,7 @@ uniform PointLight pointLights[NR_POINT_LIGHTS]; uniform int numPointLights; uniform DirLight sunLight; uniform Material material; +uniform sampler2DArray studs; // Functions @@ -61,8 +70,9 @@ void main() { for (int i = 0; i < numPointLights; i++) { result += calculatePointLight(pointLights[i]); } - - FragColor = vec4(result, 1.0); + + vec4 studPx = texture(studs, vec3(vTexCoords, vSurfaceZ)); + FragColor = vec4(mix(result, vec3(studPx), studPx.w), 1); } vec3 calculateDirectionalLight(DirLight light) { diff --git a/assets/shaders/phong.vs b/assets/shaders/phong.vs index 075cf4d..1a9a9c3 100644 --- a/assets/shaders/phong.vs +++ b/assets/shaders/phong.vs @@ -3,18 +3,60 @@ layout (location = 0) in vec3 aPos; layout (location = 1) in vec3 aNormal; layout (location = 2) in vec2 aTexCoords; +const int FaceRight = 0; +const int FaceTop = 1; +const int FaceBack = 2; +const int FaceLeft = 3; +const int FaceBottom = 4; +const int FaceFront = 5; + +const int SurfaceSmooth = 0; +const int SurfaceGlue = 1; +const int SurfaceWeld = 2; +const int SurfaceStuds = 3; +const int SurfaceInlets = 4; +const int SurfaceUniversal = 5; + out vec3 vPos; out vec3 vNormal; out vec2 vTexCoords; +flat out int vSurfaceZ; uniform mat4 model; uniform mat3 normalMatrix; uniform mat4 view; uniform mat4 projection; +uniform int surfaces[6]; +uniform vec3 texScale; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0); vPos = vec3(model * vec4(aPos, 1.0)); vNormal = normalMatrix * aNormal; + int vFace = aNormal == vec3(0,1,0) ? FaceTop : + aNormal == vec3(0, -1, 0) ? FaceBottom : + aNormal == vec3(1, 0, 0) ? FaceRight : + aNormal == vec3(-1, 0, 0) ? FaceLeft : + aNormal == vec3(0, 0, 1) ? FaceFront : + aNormal == vec3(0, 0, -1) ? FaceBack : -1; + + vSurfaceZ = surfaces[vFace]; + // if (surfaces[vFace] > SurfaceUniversal) vSurfaceZ = 0; + + switch (vFace) { + case FaceTop: + case FaceBottom: + // vTexCoords = aTexCoords * vec2(texScale.x / 2, fract(surfaceOffset + texScale.z / 12)); + vTexCoords = aTexCoords * vec2(texScale.x, texScale.z) / 2; + break; + case FaceLeft: + case FaceRight: + vTexCoords = aTexCoords * vec2(texScale.y, texScale.z) / 2; + break; + case FaceFront: + case FaceBack: + vTexCoords = aTexCoords * vec2(texScale.x, texScale.y) / 2; + break; + }; } diff --git a/assets/textures/studs.png b/assets/textures/studs.png new file mode 100644 index 0000000000000000000000000000000000000000..9b83818c915bbfb2f531b1bba3b6f36f4eb93c3d GIT binary patch literal 6031 zcmeHLX;f3mwoX6+L6nO#h{QnKqGluz5{Ss8L<}Gxqc$9plX!#-CP5-x24%1n1+hg` zP}*(~F&Z0CY^4Qfcmje*12Q>4OQQ@Th^P#&5)k#h`_@~ob?-k4H8JG%}Fqg8nRM z$exL{N`S0@GRp-6qF50+YhE;D_ zab!wyc&t0Yyz0e1^l?E(p5x|9j?bNwK7%IlsP{xu^NOQCWt-BIFGLOxM=bcu??m+| zO`|UJ4l2ueF*^~NBh;%7ZPMtBdPZD%Z$&??Kc2b3G`i#Jvwp+Q-4$xpGc&sCY_=cu zU3D?P_U^f@+ipL+{f|u#%>v71=frK#&ZWuE?Q|Qv8RQ!1_ncm}(e$?;zjM|*_47Xc zd%yi7XVdq0?Dq||8;zJK0v0JkeDbTCNLaf30sVaq=-;}QDQ>D!Z0ZViv{zTkMZ$EEY=jf zKr+b!;DaE8L=#D~mm@+)3BLk~kpUx4o5e{7?nzK3NU^ZllSqvcVgzI*6#98oN+=G1vVw_ZD~LR_6^i)~I8KBQ@nC{Tz*9{q38&k+GZ|Pip7=@Q9tughz=46?fC$25pC-Hz zKI|!llx&iy=47xU)zX|sv>*}9KN)$$VhPAZC8nx&s%DhOLI;}x#6rqE1pq2N*bCi3 z3`0_(*h?r3WnibO?$k63Tqh1Bg&ZL%3_z#qu-C^rypl+w6DPt~!m)%LguC11q;Bhpm6ZAl%9D$6})I^1iP$rM3sWiH9ZZF(?Byr*ab8ya;y zb0JV_N|`Jt&A)Z#=-|~)bg+DZW);)X&P&$R)7&g+cAQ(*|M*^pRfA>DU;d|O5-W)| z{dZT6kL$P*XZ|sFy-Tb|)1eHbii)_D7oMjw=J2X&`gqIcl%-1R<$v~W3tOdp!T)zW zPa^CeW|-wfF%z1(rie##sA=BexgmXan>H=nj01a!lrBc!;MSShI5oJS*nD3djI!s$%sA=`!+Gih{nhy=8W)r@P!gb|k z3r(*bmg2jTtylin{qmEeuHL`%ykD6&^MVtswuSIBl8r-R(hr^VJ&@)dQrh@3-`ZJp zA$REN3daKb%I?v~OFhM$l)jZuYIh6$blVD+(b6cF$9<}#Znb>*Uspym{a!s$l%*OG z*6%aRsd+Fv)O1X)t+h1!aBZDM{u8z8o<0+1AG0Z4itWP5pDyoOSL_i2yZrfU~}z_~WCsHfyasyg%grSUEe`DqH2!`j&H{-or$XPX8X z(u*Olsl|79oV)81B4{?t;WxKsC0x8&lW7qhYIgm|bZ5n$5;o&?q25iK9O?3|xTYJw z&ilJFaeHK%cKQ6$^J@0hjtHkpi0x{eZs_v<_WjD+^Ax_P=5Y=f2edVZIWYfpuq}); z_Rp0zjKzScd~aw+3axXz8jl@sT(nBVdrkdtK13E*M4yFnU!2NviCErMGVfJQ;(2Ti zrO4m5;O2>9gRJmD>eamArSb0$4!_Yp!`-;Ra_oot#JtY=f0q~$*GD|orWDP7n9-!CQGwN7m?GipZL7Cq%vTRdbl-S`EhMdJ3b zxPHynVGCA5ZtrLv5i;{!pF4z>?=9Ok`k^Sh(<~=lp=VxfI@J9;Tn*O(yLpAha_dDHX5yb}rc7THp!88^?ZyHFmV zIAc!?qvzPk`QiR4y-LMS{5Gc;_KiK9~ox7ME|+3a&LB^=7x1~Kg8_l(@F1+j(Xf% zHal_!CUWF-?yUfSyi4HB%#^pS9bVy*0Cn#(1$PMsV@oV3mtHQvC==zcL@wv7yyVV9TQA9ix7zH)#2HUFn9bsurTU7;0~c)H2~*ge)hsmwic z=>3__RWteTAGJ5E4B{HCZIE0!%X?$=r&mvP``M*i%aVg7 z9Upnu(p!)#saP_8_8pp85#Leb7jUXUGG1T6`AsprU3dB-diM15G0S8E>VGPt`B&y0Ru}cv0BgAWqWJ z1nZU2#T?0?Nl0zXna&S!8Obpw-chv!F-fyg!xyl2zbv(yp^vq**Po$p>UB-wyWP`f=&N6@T9P$wZ*tsEm parts; Skybox* skyboxTexture = NULL; +Texture3D* studsTexture = NULL; void renderInit(GLFWwindow* window) { glViewport(0, 0, 1200, 900); @@ -31,6 +32,10 @@ void renderInit(GLFWwindow* window) { initMeshes(); glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + // glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + skyboxTexture = new Skybox({ "assets/textures/skybox/null_plainsky512_lf.jpg", @@ -41,6 +46,8 @@ void renderInit(GLFWwindow* window) { "assets/textures/skybox/null_plainsky512_bk.jpg", }, GL_RGB); + studsTexture = new Texture3D("assets/textures/studs.png", 64, 64, 6, GL_RGBA); + // Compile shader shader = new Shader("assets/shaders/phong.vs", "assets/shaders/phong.fs"); skyboxShader = new Shader("assets/shaders/skybox.vs", "assets/shaders/skybox.fs"); @@ -81,6 +88,10 @@ void renderParts() { // .linear = 0.9, // .quadratic = 0.32, // }); + studsTexture->activate(0); + shader->set("studs", 0); + shader->set("surfaces[1]", 3); + shader->set("surfaces[4]", 4); // Pre-calculate the normal matrix for the shader @@ -96,6 +107,7 @@ void renderParts() { shader->set("material", part.material); glm::mat3 normalMatrix = glm::mat3(glm::transpose(glm::inverse(model))); shader->set("normalMatrix", normalMatrix); + shader->set("texScale", part.scale); CUBE_MESH->bind(); glDrawArrays(GL_TRIANGLES, 0, 36); diff --git a/src/rendering/texture.cpp b/src/rendering/texture.cpp index fce10b5..fe6b87a 100644 --- a/src/rendering/texture.cpp +++ b/src/rendering/texture.cpp @@ -4,7 +4,7 @@ #include #include -Texture::Texture(const char* texturePath, unsigned int format) { +Texture::Texture(const char* texturePath, unsigned int format, bool noMipMaps) { glGenTextures(1, &this->ID); glBindTexture(GL_TEXTURE_2D, this->ID); @@ -28,7 +28,7 @@ Texture::Texture(const char* texturePath, unsigned int format) { glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); + if (!noMipMaps) glGenerateMipmap(GL_TEXTURE_2D); stbi_image_free(data); } diff --git a/src/rendering/texture.h b/src/rendering/texture.h index c7ac8a6..eca0e3b 100644 --- a/src/rendering/texture.h +++ b/src/rendering/texture.h @@ -6,7 +6,7 @@ class Texture { private: unsigned int ID; public: - Texture(const char* texturePath, unsigned format = GL_RGB); + Texture(const char* texturePath, unsigned format = GL_RGB, bool noMipMaps = false); ~Texture(); void activate(unsigned int textureIdx); diff --git a/src/rendering/texture3d.cpp b/src/rendering/texture3d.cpp new file mode 100644 index 0000000..e5d0c84 --- /dev/null +++ b/src/rendering/texture3d.cpp @@ -0,0 +1,43 @@ +#include "texture3d.h" + +#include +#include +#include + +Texture3D::Texture3D(const char* texturePath, unsigned int tileWidth, unsigned int tileHeight, unsigned int tileCount, unsigned int format) { + glGenTextures(1, &this->ID); + glBindTexture(GL_TEXTURE_2D_ARRAY, this->ID); + + // Wrapping + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_REPEAT); + + // Interpolation + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // stbi_set_flip_vertically_on_load(true); + int width, height, nrChannels; + unsigned char *data = stbi_load(texturePath, &width, &height, + &nrChannels, 0); + + if (!data) { + printf("Failed to load texture '%s'\n", texturePath); + abort(); + } + + glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, format, tileWidth, tileHeight, /* no of layers= */ tileCount, 0, format, + GL_UNSIGNED_BYTE, data); + + stbi_image_free(data); +} + +Texture3D::~Texture3D() { + glDeleteTextures(1, &this->ID); +} + +void Texture3D::activate(unsigned int textureIdx) { + glActiveTexture(GL_TEXTURE0 + textureIdx); + glBindTexture(GL_TEXTURE_2D, this->ID); +} diff --git a/src/rendering/texture3d.h b/src/rendering/texture3d.h new file mode 100644 index 0000000..86ab7b3 --- /dev/null +++ b/src/rendering/texture3d.h @@ -0,0 +1,13 @@ +#pragma once + +#define GL_RGB 0x1907 + +class Texture3D { +private: + unsigned int ID; +public: + Texture3D(const char* texturePath, unsigned int tileWidth, unsigned int tileHeight, unsigned int tileCount, unsigned format = GL_RGB); + ~Texture3D(); + + void activate(unsigned int textureIdx); +};