mirror of
https://github.com/sigonasr2/Shep.git
synced 2026-08-18 05:43:22 -05:00
Switch to Hardware3D Util
This commit is contained in:
parent
0692ffb68a
commit
1ee5f4ec80
@ -351,10 +351,13 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="miniaudio.h" />
|
||||
<ClInclude Include="olcPGEX_Graphics3D.h" />
|
||||
<ClInclude Include="olcPGEX_MiniAudio.h" />
|
||||
<ClInclude Include="olcPixelGameEngine.h" />
|
||||
<ClInclude Include="olcUTIL_Geometry2D.h" />
|
||||
<ClInclude Include="olcUTIL_Hardware3D.h">
|
||||
<SubType>
|
||||
</SubType>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@ -29,9 +29,6 @@
|
||||
<ClInclude Include="miniaudio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcPGEX_Graphics3D.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcPGEX_MiniAudio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -44,5 +41,8 @@
|
||||
<ClInclude Include="util.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="olcUTIL_Hardware3D.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
280
main.cpp
280
main.cpp
@ -1,120 +1,220 @@
|
||||
#include "olcPixelGameEngine.h"
|
||||
#include "olcPGEX_Graphics3D.h"
|
||||
#include "util.h"
|
||||
/*
|
||||
Example file for olcUTIL_Hardware3D.h
|
||||
|
||||
class ShepGame : public olc::PixelGameEngine
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2018 - 2025 OneLoneCoder.com
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above
|
||||
copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce
|
||||
the above copyright notice. This list of conditions and the following
|
||||
disclaimer must be reproduced in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Links
|
||||
~~~~~
|
||||
YouTube: https://www.youtube.com/javidx9
|
||||
Discord: https://discord.gg/WhwHUMV
|
||||
Twitter: https://www.twitter.com/javidx9
|
||||
Twitch: https://www.twitch.tv/javidx9
|
||||
GitHub: https://www.github.com/onelonecoder
|
||||
Homepage: https://www.onelonecoder.com
|
||||
|
||||
Author
|
||||
~~~~~~
|
||||
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022, 2023, 2024, 2025
|
||||
|
||||
*/
|
||||
|
||||
|
||||
//#define OLC_GFX_OPENGL33
|
||||
#include "olcUTIL_Hardware3D.h"
|
||||
#include "olcPixelGameEngine.h"
|
||||
|
||||
|
||||
|
||||
class Quad3D : public olc::PixelGameEngine
|
||||
{
|
||||
public:
|
||||
ShepGame()
|
||||
Quad3D()
|
||||
{
|
||||
// Name your application
|
||||
sAppName = "Shep";
|
||||
sAppName = "Hardware3D Assetless Demo";
|
||||
}
|
||||
|
||||
olc::mf4d matWorld;
|
||||
olc::mf4d matView;
|
||||
olc::mf4d matProject;
|
||||
|
||||
olc::Renderable texCube;
|
||||
olc::utils::hw3d::mesh meshCube;
|
||||
olc::utils::hw3d::mesh meshLightCube;
|
||||
|
||||
std::array<olc::vf3d, 64> cubes;
|
||||
std::array<olc::vf3d, 3> lights;
|
||||
|
||||
public:
|
||||
|
||||
const vi2d SCREEN_SIZE{256,192};
|
||||
|
||||
Renderable space,nico;
|
||||
GFX3D::PipeLine renderer;
|
||||
GFX3D::vec3d vUp{0,0,1};
|
||||
GFX3D::vec3d vEye{0.f,-5.f,2.f};
|
||||
GFX3D::mat4x4 camRot{GFX3D::Math::Mat_MakeRotationX(util::degToRad(5))};
|
||||
GFX3D::vec3d vLookDir{GFX3D::Math::Mat_MultiplyVector(camRot,{0,0,1})};
|
||||
|
||||
bool OnUserCreate() override
|
||||
{
|
||||
olc::GFX3D::ConfigureDisplay();
|
||||
renderer.SetProjection(90.0f, (float)SCREEN_SIZE.x/(float)SCREEN_SIZE.y, 0.1f, 1000.0f, 0, SCREEN_SIZE.y, 512, SCREEN_SIZE.y);
|
||||
space.Load("assets/gfx/space.png");
|
||||
nico.Load("assets/gfx/nico-Trapper_512.png");
|
||||
float fAspect = float(GetScreenSize().y) / float(GetScreenSize().x);
|
||||
float S = 1.0f / (tan(3.14159f * 0.25f));
|
||||
float f = 1000.0f;
|
||||
float n = 0.1f;
|
||||
|
||||
matProject(0, 0) = fAspect; matProject(0, 1) = 0.0f; matProject(0, 2) = 0.0f; matProject(0, 3) = 0.0f;
|
||||
matProject(1, 0) = 0.0f; matProject(1, 1) = 1; matProject(1, 2) = 0.0f; matProject(1, 3) = 0.0f;
|
||||
matProject(2, 0) = 0.0f; matProject(2, 1) = 0.0f; matProject(2, 2) = -(f / (f - n)); matProject(2, 3) = -1.0f;
|
||||
matProject(3, 0) = 0.0f; matProject(3, 1) = 0.0f; matProject(3, 2) = -((f * n) / (f - n)); matProject(3, 3) = 0.0f;
|
||||
|
||||
matWorld.identity();
|
||||
matView.identity();
|
||||
|
||||
// Create a unit cube, centered on origin
|
||||
meshCube = olc::utils::hw3d::CreateCube({ 1,1,1 }, {-0.5, -0.5, -0.5});
|
||||
|
||||
// Creat another cube, smaller
|
||||
meshLightCube = olc::utils::hw3d::CreateCube({ 0.5,0.5,0.5 }, { -0.25, -0.25, -0.25 });
|
||||
|
||||
// Why 2 cubes? the regular ones will have their vertex information recoloured
|
||||
|
||||
// Create texture (so we dont need to load anything)
|
||||
texCube.Create(128, 128);
|
||||
SetDrawTarget(texCube.Sprite());
|
||||
Clear(olc::WHITE);
|
||||
FillCircle(64, 64, 32, olc::BLACK);
|
||||
FillCircle(64, 64, 24, olc::BLUE);
|
||||
FillCircle(64, 64, 16, olc::RED);
|
||||
FillCircle(64, 64, 8, olc::YELLOW);
|
||||
SetDrawTarget(nullptr);
|
||||
texCube.Decal()->Update();
|
||||
|
||||
// Position cubes nicely
|
||||
for(int x=0; x<8; x++)
|
||||
for (int y = 0; y < 8; y++)
|
||||
{
|
||||
float z = sin(float(x)) + cos(float(y));
|
||||
cubes[y * 8 + x] = { float(x) - 4.0f, float(z), float(y) - 4.0f };
|
||||
}
|
||||
|
||||
|
||||
Clear(olc::VERY_DARK_BLUE);
|
||||
HW3D_Projection(matProject.m);
|
||||
HW3D_SetCullMode(olc::CullMode::CCW);
|
||||
return true;
|
||||
}
|
||||
|
||||
float fThetaX = 1;
|
||||
float fThetaY = 2;
|
||||
|
||||
float fLightTime = 0.0f;
|
||||
|
||||
olc::vf3d pos;
|
||||
|
||||
|
||||
bool OnUserUpdate(float fElapsedTime) override
|
||||
{
|
||||
|
||||
DrawDecal({},space.Decal(),{1.f,1.f},WHITE,olc::GFX3DTransform::TRANSFORM_REQUIRED);
|
||||
olc::mf4d m1, m2, m3, m4;
|
||||
|
||||
// fake a pseudo-view matrix by transforming in an identity view
|
||||
m1.rotateY(fThetaY);
|
||||
m2.rotateX(fThetaX);
|
||||
m3.translate(pos.x,pos.y,pos.z);
|
||||
|
||||
using namespace olc;
|
||||
|
||||
if(GetKey(olc::Key::RIGHT).bHeld)pos.x+=fElapsedTime*5;
|
||||
if(GetKey(olc::Key::LEFT).bHeld)pos.x-=fElapsedTime*5;
|
||||
if(GetKey(olc::Key::UP).bHeld)pos.y-=fElapsedTime*5;
|
||||
if(GetKey(olc::Key::DOWN).bHeld)pos.y+=fElapsedTime*5;
|
||||
if(GetKey(olc::Key::PGUP).bHeld)pos.z-=fElapsedTime*5;
|
||||
if(GetKey(olc::Key::PGDN).bHeld)pos.z+=fElapsedTime*5;
|
||||
|
||||
|
||||
matView = m3 * m2 * m1;
|
||||
|
||||
// Clear background
|
||||
ClearBuffer(olc::BLANK, true);
|
||||
|
||||
DrawDecal({},nico.Decal(),{1.f,1.f},WHITE,olc::GFX3DTransform::POPUP_SPRITE);
|
||||
// Update light positions
|
||||
fLightTime += fElapsedTime;
|
||||
lights[0] = { 6.0f * sin(fLightTime * 2.5f), 6.0f * cos(fLightTime * 2.5f), 0.0f };
|
||||
lights[1] = { 0.0f, 6.0f * sin(fLightTime), 6.0f * cos(fLightTime) };
|
||||
lights[2] = { 6.0f * cos(fLightTime * 1.7f), 0.0f, 6.0f * sin(fLightTime * 1.7f) };
|
||||
|
||||
// World Space lighting! The 3 lights are used as directional light sources
|
||||
// so i dont need to pre-compute all the geometry on the CPU. This is a
|
||||
// limitation of the hw3d approach but like I said, its for basic 3D usage.
|
||||
for (size_t i = 0; i < meshCube.pos.size(); i += 3)
|
||||
{
|
||||
const auto& p0 = meshCube.pos[i + 0];
|
||||
const auto& p1 = meshCube.pos[i + 1];
|
||||
const auto& p2 = meshCube.pos[i + 2];
|
||||
|
||||
// Hand calculate surface normal (i know i know the norms are already there...)
|
||||
olc::vf3d vCross = olc::vf3d(p1[0] - p0[0], p1[1] - p0[1], p1[2] - p0[2]).cross(olc::vf3d(p2[0] - p0[0], p2[1] - p0[1], p2[2] - p0[2])).norm();
|
||||
|
||||
if(GetKey(LEFT).bHeld)vEye.x-=fElapsedTime*5;
|
||||
if(GetKey(RIGHT).bHeld)vEye.x+=fElapsedTime*5;
|
||||
if(GetKey(UP).bHeld)vEye.z+=fElapsedTime*5;
|
||||
if(GetKey(DOWN).bHeld)vEye.z-=fElapsedTime*5;
|
||||
if(GetKey(PGUP).bHeld)vEye.y+=fElapsedTime*5;
|
||||
if(GetKey(PGDN).bHeld)vEye.y-=fElapsedTime*5;
|
||||
return true;
|
||||
}
|
||||
virtual void Apply3DTransform(std::vector<DecalInstance>&decals)override{
|
||||
std::vector<DecalInstance>oldDecals;
|
||||
//std::vector<DecalInstance>foregroundDecals;
|
||||
oldDecals.reserve(decals.size());
|
||||
std::copy(decals.begin(),decals.end(),std::back_inserter(oldDecals));
|
||||
decals.clear();
|
||||
GFX3D::vec3d vLookTarget = GFX3D::Math::Vec_Add(vEye, vLookDir);
|
||||
renderer.SetCamera(vEye,vLookTarget,vUp);
|
||||
// Additive colouring
|
||||
meshCube.col[i + 0] = olc::BLACK;
|
||||
meshCube.col[i + 1] = olc::BLACK;
|
||||
meshCube.col[i + 2] = olc::BLACK;
|
||||
|
||||
GFX3D::mat4x4 matRotateX=GFX3D::Math::Mat_MakeRotationX(0.f);
|
||||
GFX3D::mat4x4 matRotateZ=GFX3D::Math::Mat_MakeRotationZ(0.f);
|
||||
|
||||
GFX3D::mat4x4 matWorld=GFX3D::Math::Mat_MultiplyMatrix(matRotateX,matRotateZ);
|
||||
|
||||
renderer.SetTransform(matWorld);
|
||||
|
||||
float zIncrementer{0.f};
|
||||
|
||||
for(DecalInstance&decal:oldDecals){
|
||||
SetDecalMode(decal.mode);
|
||||
if(decal.points==0)continue;
|
||||
if(decal.points==3){
|
||||
GFX3D::triangle tri{{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}};
|
||||
tri.p[0].z+=zIncrementer;
|
||||
tri.p[1].z+=zIncrementer;
|
||||
tri.p[2].z+=zIncrementer;
|
||||
renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
|
||||
if(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f){
|
||||
tri.col[0]=tri.col[1]=tri.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))};
|
||||
tri.p[0].z=tri.p[1].z=tri.p[2].z=0.1f+zIncrementer;
|
||||
renderer.Render({tri},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
|
||||
}
|
||||
}else if(decal.points==4){
|
||||
GFX3D::triangle tri,tri2;
|
||||
if(decal.transform==GFX3DTransform::POPUP_SPRITE){ //Orientation is lower-left clockwise
|
||||
tri={{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.decal->sprite->height+decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.decal->sprite->height+decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}};
|
||||
tri2={{{decal.pos[0].x,decal.pos[0].y,decal.decal->sprite->height+decal.z[0],1.f},{decal.pos[2].x,decal.pos[2].y,decal.decal->sprite->height+decal.z[2],1.f},{decal.pos[3].x,decal.pos[3].y,decal.z[3],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f},{decal.uv[3].x,decal.uv[3].y,0.f}},{decal.tint[0],decal.tint[2],decal.tint[3]}};
|
||||
}else{
|
||||
tri={{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[1].x,decal.pos[1].y,decal.z[1],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[1].x,decal.uv[1].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f}},{decal.tint[0],decal.tint[1],decal.tint[2]}};
|
||||
tri2={{{decal.pos[0].x,decal.pos[0].y,decal.z[0],1.f},{decal.pos[2].x,decal.pos[2].y,decal.z[2],1.f},{decal.pos[3].x,decal.pos[3].y,decal.z[3],1.f}},{{decal.uv[0].x,decal.uv[0].y,0.f},{decal.uv[2].x,decal.uv[2].y,0.f},{decal.uv[3].x,decal.uv[3].y,0.f}},{decal.tint[0],decal.tint[2],decal.tint[3]}};
|
||||
}
|
||||
tri.p[0].z+=zIncrementer;
|
||||
tri.p[1].z+=zIncrementer;
|
||||
tri.p[2].z+=zIncrementer;
|
||||
tri2.p[0].z+=zIncrementer;
|
||||
tri2.p[1].z+=zIncrementer;
|
||||
tri2.p[2].z+=zIncrementer;
|
||||
renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
|
||||
if(decal.z[0]>0.1f||decal.z[1]>0.1f||decal.z[2]>0.1f||decal.z[3]>0.1f){
|
||||
tri.col[0]=tri.col[1]=tri.col[2]=tri2.col[0]=tri2.col[1]=tri2.col[2]={0,0,0,uint8_t(util::lerp(0,160,(1/std::pow(decal.z[0]/10.f+1,4))))};
|
||||
tri.p[0].z=tri.p[1].z=tri.p[2].z=tri2.p[0].z=tri2.p[1].z=tri2.p[2].z=0.1f+zIncrementer;
|
||||
renderer.Render({tri,tri2},decal.decal,GFX3D::RENDER_TEXTURED|GFX3D::RENDER_DEPTH);
|
||||
}
|
||||
}else{
|
||||
|
||||
olc::Pixel c[] = { olc::RED, olc::GREEN, olc::BLUE };
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
olc::vf3d vLight = -lights[j].norm();
|
||||
float illum = std::max(-vCross.dot(vLight), 0.0f) * 0.8f + 0.2f;
|
||||
meshCube.col[i + 0] += olc::PixelF(illum, illum, illum, 1.0f) * c[j];
|
||||
meshCube.col[i + 1] += olc::PixelF(illum, illum, illum, 1.0f) * c[j];
|
||||
meshCube.col[i + 2] += olc::PixelF(illum, illum, illum, 1.0f) * c[j];
|
||||
}
|
||||
SetDecalMode(DecalMode::NORMAL);
|
||||
zIncrementer+=0.000001f;
|
||||
}
|
||||
|
||||
std::sort(decals.begin(),decals.end(),[](const DecalInstance&d1,const DecalInstance&d2){return d1.z[0]>d2.z[0];});
|
||||
|
||||
// Draw all cubes
|
||||
for (const auto& cube : cubes)
|
||||
{
|
||||
matWorld.translate(cube);
|
||||
HW3D_DrawObject((matView * matWorld).m, texCube.Decal(), meshCube.layout, meshCube.pos, meshCube.uv, meshCube.col);
|
||||
}
|
||||
|
||||
// Draw light cubes
|
||||
matWorld.translate(lights[0]);
|
||||
HW3D_DrawObject((matView * matWorld).m, nullptr, meshLightCube.layout, meshLightCube.pos, meshLightCube.uv, meshLightCube.col, olc::RED);
|
||||
matWorld.translate(lights[1]);
|
||||
HW3D_DrawObject((matView * matWorld).m, nullptr, meshLightCube.layout, meshLightCube.pos, meshLightCube.uv, meshLightCube.col, olc::GREEN);
|
||||
matWorld.translate(lights[2]);
|
||||
HW3D_DrawObject((matView * matWorld).m, nullptr, meshLightCube.layout, meshLightCube.pos, meshLightCube.uv, meshLightCube.col, olc::BLUE);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
ShepGame demo;
|
||||
if (demo.Construct(256, 240, 4, 4))
|
||||
Quad3D demo;
|
||||
if (demo.Construct(1280, 720, 1, 1, false, false))
|
||||
demo.Start();
|
||||
return 0;
|
||||
}
|
||||
1147
olcPGEX_Graphics3D.h
1147
olcPGEX_Graphics3D.h
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,3 @@
|
||||
#define OLC_PGE_APPLICATION
|
||||
#include "olcPixelGameEngine.h"
|
||||
|
||||
#define OLC_PGEX_GRAPHICS3D
|
||||
#include "olcPGEX_Graphics3D.h"
|
||||
3325
olcPixelGameEngine.h
3325
olcPixelGameEngine.h
File diff suppressed because it is too large
Load Diff
1389
olcUTIL_Hardware3D.h
Normal file
1389
olcUTIL_Hardware3D.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user