Start day 26 Advanced Data and Advanced GLSL.

This commit is contained in:
Zed A. Shaw 2026-09-05 13:46:09 -04:00
parent 9310215aa3
commit 6c542eb014
119 changed files with 15705 additions and 0 deletions

10
26-advanced-data-glsl/.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
.*.sw*
.DS_Store
*.sqlite3
*.sqlite3-wal
*.sqlite3-shm
debug
coverage/
.coverage
builddir
subprojects

View file

@ -0,0 +1 @@
set makeprg=meson\ compile\ -C\ .

View file

@ -0,0 +1,16 @@
MIT No Attribution
Copyright <YEAR> <COPYRIGHT HOLDER>
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,30 @@
all: build
reset:
powershell -executionpolicy bypass .\scripts\reset_build.ps1
build:
meson compile -j 4 -C builddir
release_build:
meson --wipe builddir -Db_ndebug=true --buildtype release
meson compile -j 4 -C builddir
debug_build:
meson setup --wipe builddir -Db_ndebug=true --buildtype debugoptimized
meson compile -j 4 -C builddir
run: test
./builddir/hellogl.exe
test: build
./builddir/fuc2it
debug_test: build
gdb --nx -x .gdbinit --ex run --args builddir/fuc2it.exe
debug_run: build
gdb --nx -x .gdbinit --batch --ex run --ex bt --ex q --args builddir/hellogl.exe
clean:
meson compile --clean -C builddir

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,4 @@
# Made in Blockbench 5.1.6
newmtl m_cd2bce81-4f84-6efd-a971-2b9e91f19e2f
map_Kd container2.png
newmtl none

View file

@ -0,0 +1,49 @@
# Made in Blockbench 5.1.6
mtllib crate.mtl
o cube
v 0.1875 0.4375 0.375
v 0.1875 0.4375 -0.0625
v 0.1875 0 0.375
v 0.1875 0 -0.0625
v -0.25 0.4375 -0.0625
v -0.25 0.4375 0.375
v -0.25 0 -0.0625
v -0.25 0 0.375
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vt 0 1
vt 1 1
vt 1 0
vt 0 0
vn 0 0 -1
vn 1 0 0
vn 0 0 1
vn -1 0 0
vn 0 1 0
vn 0 -1 0
usemtl m_cd2bce81-4f84-6efd-a971-2b9e91f19e2f
f 4/4/1 7/3/1 5/2/1 2/1/1
f 3/8/2 4/7/2 2/6/2 1/5/2
f 8/12/3 3/11/3 1/10/3 6/9/3
f 7/16/4 8/15/4 6/14/4 5/13/4
f 6/20/5 1/19/5 2/18/5 5/17/5
f 7/24/6 4/23/6 3/22/6 8/21/6

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,124 @@
{
"scene": {
"shader": {
"vertex_path": "shaders/21-framebuffers.vert.glsl",
"frag_path": "shaders/21-framebuffers.frag.glsl"
},
"reflect_shader": {
"vertex_path": "shaders/24-vert.glsl",
"frag_path": "shaders/24-frag.glsl"
},
"screen_shader": {
"vertex_path": "shaders/21-screen.vert.glsl",
"frag_path": "shaders/21-screen.frag.glsl"
},
"skybox_shader": {
"vertex_path": "shaders/24-skybox.vert.glsl",
"frag_path": "shaders/24-skybox.frag.glsl"
},
"skybox_faces": [
"../assets/skybox/sky/right.jpg",
"../assets/skybox/sky/left.jpg",
"../assets/skybox/sky/top.jpg",
"../assets/skybox/sky/bottom.jpg",
"../assets/skybox/sky/front.jpg",
"../assets/skybox/sky/back.jpg"
],
"materials": {
"default": {
"ambient": [0.5, 0.5, 0.5],
"shininess": 32.0,
"diffuseMap": 0,
"specularMap": 0
},
"shiny": {
"ambient": [0.5, 0.5, 0.5],
"shininess": 10000.0,
"diffuseMap": 0,
"specularMap": 0
}
},
"models": {
"marble_cube": {
"directory": "assets",
"model_path": "marble_cube.glb"
},
"metal_floor": {
"directory": "assets",
"model_path": "metal_floor.glb"
},
"grass": {
"directory": "assets",
"model_path": "grass.glb"
},
"window": {
"directory": "assets",
"model_path": "window.glb"
}
},
"things": [
{"model": "marble_cube", "position": [1.5, 0.0, -1.0],
"rotation": {"angle": 0.0, "axes": [1.0, 1.0, 1.0]},
"scale": 3.0,
"material": "default"},
{"model": "marble_cube", "position": [1.5, 0.25, 0.0],
"rotation": {"angle": 90.0, "axes": [1.0,0.0,0.0]},
"scale": 1.0,
"material": "shiny"}
],
"camera": {
"position": [0.0, 0.1, 3.0],
"front": [0.0, 0.0, -1.0],
"up": [0.0, 1.0, 0.0],
"direction": [0.0, 0.0, 0.0],
"movement_speed": 10.0
},
"light": {
"directional": [
{
"position": [0, 0, 0.0],
"direction":[-0.2, -1.0, -0.3],
"ambient":[0.2, 0.2, 0.2],
"diffuse":[0.8, 0.8, 0.8],
"specular":[1.0, 1.0, 1.0],
"constant": 0.0,
"linear": 0.0,
"quadratic": 0.0,
"cut_off": 0.0,
"outer_cut_off": 0.0,
"on": true
}
],
"positioned": [
{
"position": [1.2, 1.0, 2.0],
"direction":[-0.2, -1.0, -0.3],
"ambient":[0.2, 0.2, 0.2],
"diffuse":[0.8, 0.8, 0.8],
"specular":[1.0, 1.0, 1.0],
"constant": 1.0,
"linear": 0.09,
"quadratic": 0.032,
"cut_off": 12.5,
"outer_cut_off": 17.5,
"on": true
}
],
"spot": [
],
"camera": {
"position":[2.2, 1.0, 2.0],
"direction":[0.0, 0.0, -1.0],
"ambient":[0.2, 0.2, 0.2],
"diffuse":[0.8, 0.8, 0.8],
"specular":[1.0, 1.0, 1.0],
"constant": 1.0,
"linear": 0.09,
"quadratic": 0.032,
"cut_off": 12.5,
"outer_cut_off": 17.5,
"on": true
}
}
}
}

View file

@ -0,0 +1,103 @@
project('hellogl', 'cpp',
version: '0.1.0',
default_options: [
'cpp_std=c++23',
'cpp_args=-D_GLIBCXX_DEBUG=1 -D_GLIBCXX_DEBUG_PEDANTIC=1',
])
# use this for common options only for our executables
cpp_args=[
'-Wno-unused-parameter',
'-Wno-unused-function',
'-Wno-unused-variable',
'-Wno-unused-but-set-variable',
'-Wno-deprecated-declarations',
]
link_args=[]
# these are passed as override_defaults
exe_defaults = [ 'warning_level=2' ]
cc = meson.get_compiler('cpp')
dependencies = []
if build_machine.system() == 'windows'
add_global_link_arguments(
'-static-libgcc',
'-static-libstdc++',
'-static',
'-lstdc++exp',
language: 'cpp',
)
opengl32 = cc.find_library('opengl32', required: true)
winmm = cc.find_library('winmm', required: true)
gdi32 = cc.find_library('gdi32', required: true)
dependencies += [
opengl32, winmm, gdi32
]
exe_defaults += ['werror=true']
elif build_machine.system() == 'darwin'
add_global_link_arguments(
language: 'cpp',
)
opengl = dependency('OpenGL')
corefoundation = dependency('CoreFoundation')
carbon = dependency('Carbon')
cocoa = dependency('Cocoa')
iokit = dependency('IOKit')
corevideo = dependency('CoreVideo')
link_args += ['-ObjC']
exe_defaults += ['werror=false']
dependencies += [
opengl, corefoundation, carbon, cocoa, iokit, corevideo
]
endif
glfw3 = subproject('glfw').get_variable('glfw_dep')
fuc2 = subproject('fuc2').get_variable('fuc2_dep')
fmt = subproject('fmt').get_variable('fmt_dep')
glm = subproject('glm').get_variable('glm_dep')
json = subproject('nlohmann_json').get_variable('nlohmann_json_dep')
assimp = subproject('assimp').get_variable('assimp_dep')
dependencies += [
glfw3, fuc2, fmt, glm, assimp, json
]
inc_dirs = ['src']
sources = [
'src/glad/glad.cpp',
'src/dbc.cpp',
'src/stb_image.cpp',
'src/shader.cpp',
'src/mesh.cpp',
'src/utils.cpp',
'src/model.cpp',
'src/scene.cpp',
'src/camera.cpp',
'src/framebuffer.cpp',
'src/screen.cpp',
]
subdir('tests')
executable('fuc2it', sources + fuc2_tests,
cpp_args: cpp_args,
link_args: link_args,
include_directories: inc_dirs,
override_options: exe_defaults,
dependencies: dependencies + [fuc2])
executable('hellogl',
sources + [ 'src/main.cpp' ],
cpp_args: cpp_args,
include_directories: inc_dirs,
link_args: link_args,
override_options: exe_defaults,
dependencies: dependencies)

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,7 @@
mv .\subprojects\packagecache .
rm -recurse -force .\subprojects\,.\builddir\
mkdir subprojects
mv .\packagecache .\subprojects\
mkdir builddir
cp wraps\*.wrap subprojects\
meson setup --default-library=static --prefer-static builddir

View file

@ -0,0 +1,10 @@
#!/usr/bin/env bash
mv -f ./subprojects/packagecache .
rm -rf subprojects builddir
mkdir subprojects
mv -f packagecache ./subprojects/ && true
mkdir builddir
cp wraps/*.wrap subprojects/
# on OSX you can't do this with static
meson setup --default-library=static --prefer-static builddir

View file

@ -0,0 +1,4 @@
mkdir builddir
mkdir subprojects
cp wraps/*.wrap subprojects
meson setup -Ddefault_library=static builddir

View file

@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -ex
mkdir subprojects
mkdir builddir
cp wraps/*.wrap subprojects/
meson setup builddir

View file

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
fswatch -o *.cpp | while read num
do echo ">>>>>>>>>>>>>>>>>>>>>> `date`"
if meson compile -C builddir
then
./builddir/sfmldemo
else
echo "^^^^^^^^^^^^^^^^^^^^^ ERROR `date`"
fi
done

View file

@ -0,0 +1,255 @@
function Test-WinUtilPackageManager {
<#
.SYNOPSIS
Checks if Winget and/or Choco are installed
.PARAMETER winget
Check if Winget is installed
.PARAMETER choco
Check if Chocolatey is installed
#>
Param(
[System.Management.Automation.SwitchParameter]$winget,
[System.Management.Automation.SwitchParameter]$choco
)
$status = "not-installed"
if ($winget) {
# Check if Winget is available while getting it's Version if it's available
$wingetExists = $true
try {
$wingetVersionFull = winget --version
} catch [System.Management.Automation.CommandNotFoundException], [System.Management.Automation.ApplicationFailedException] {
Write-Warning "Winget was not found due to un-availablity reasons"
$wingetExists = $false
} catch {
Write-Warning "Winget was not found due to un-known reasons, The Stack Trace is:`n$($psitem.Exception.StackTrace)"
$wingetExists = $false
}
# If Winget is available, Parse it's Version and give proper information to Terminal Output.
# If it isn't available, the return of this funtion will be "not-installed", indicating that
# Winget isn't installed/available on The System.
if ($wingetExists) {
# Check if Preview Version
if ($wingetVersionFull.Contains("-preview")) {
$wingetVersion = $wingetVersionFull.Trim("-preview")
$wingetPreview = $true
} else {
$wingetVersion = $wingetVersionFull
$wingetPreview = $false
}
# Check if Winget's Version is too old.
$wingetCurrentVersion = [System.Version]::Parse($wingetVersion.Trim('v'))
# Grabs the latest release of Winget from the Github API for version check process.
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop
$wingetLatestVersion = [System.Version]::Parse(($response.tag_name).Trim('v')) #Stores version number of latest release.
$wingetOutdated = $wingetCurrentVersion -lt $wingetLatestVersion
Write-Host "===========================================" -ForegroundColor Green
Write-Host "--- Winget is installed ---" -ForegroundColor Green
Write-Host "===========================================" -ForegroundColor Green
Write-Host "Version: $wingetVersionFull" -ForegroundColor White
if (!$wingetPreview) {
Write-Host " - Winget is a release version." -ForegroundColor Green
} else {
Write-Host " - Winget is a preview version. Unexpected problems may occur." -ForegroundColor Yellow
}
if (!$wingetOutdated) {
Write-Host " - Winget is Up to Date" -ForegroundColor Green
$status = "installed"
}
else {
Write-Host " - Winget is Out of Date" -ForegroundColor Red
$status = "outdated"
}
} else {
Write-Host "===========================================" -ForegroundColor Red
Write-Host "--- Winget is not installed ---" -ForegroundColor Red
Write-Host "===========================================" -ForegroundColor Red
$status = "not-installed"
}
}
if ($choco) {
if ((Get-Command -Name choco -ErrorAction Ignore) -and ($chocoVersion = (Get-Item "$env:ChocolateyInstall\choco.exe" -ErrorAction Ignore).VersionInfo.ProductVersion)) {
Write-Host "===========================================" -ForegroundColor Green
Write-Host "--- Chocolatey is installed ---" -ForegroundColor Green
Write-Host "===========================================" -ForegroundColor Green
Write-Host "Version: v$chocoVersion" -ForegroundColor White
$status = "installed"
} else {
Write-Host "===========================================" -ForegroundColor Red
Write-Host "--- Chocolatey is not installed ---" -ForegroundColor Red
Write-Host "===========================================" -ForegroundColor Red
$status = "not-installed"
}
}
return $status
}
function Get-WinUtilWingetPrerequisites {
<#
.SYNOPSIS
Downloads the Winget Prereqs.
.DESCRIPTION
Downloads Prereqs for Winget. Version numbers are coded as variables and can be updated as uncommonly as Microsoft updates the prereqs.
#>
# I don't know of a way to detect the prereqs automatically, so if someone has a better way of defining these, that would be great.
# Microsoft.VCLibs version rarely changes, but for future compatibility I made it a variable.
$versionVCLibs = "14.00"
$fileVCLibs = "https://aka.ms/Microsoft.VCLibs.x64.${versionVCLibs}.Desktop.appx"
# Write-Host "$fileVCLibs"
# Microsoft.UI.Xaml version changed recently, so I made the version numbers variables.
$versionUIXamlMinor = "2.8"
$versionUIXamlPatch = "2.8.6"
$fileUIXaml = "https://github.com/microsoft/microsoft-ui-xaml/releases/download/v${versionUIXamlPatch}/Microsoft.UI.Xaml.${versionUIXamlMinor}.x64.appx"
# Write-Host "$fileUIXaml"
Try{
Write-Host "Downloading Microsoft.VCLibs Dependency..."
Invoke-WebRequest -Uri $fileVCLibs -OutFile $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx
Write-Host "Downloading Microsoft.UI.Xaml Dependency...`n"
Invoke-WebRequest -Uri $fileUIXaml -OutFile $ENV:TEMP\Microsoft.UI.Xaml.x64.appx
}
Catch{
throw [WingetFailedInstall]::new('Failed to install prerequsites')
}
}
function Get-WinUtilWingetLatest {
<#
.SYNOPSIS
Uses GitHub API to check for the latest release of Winget.
.DESCRIPTION
This function grabs the latest version of Winget and returns the download path to Install-WinUtilWinget for installation.
#>
# Invoke-WebRequest is notoriously slow when the byte progress is displayed. The following lines disable the progress bar and reset them at the end of the function
$PreviousProgressPreference = $ProgressPreference
$ProgressPreference = "silentlyContinue"
Try{
# Grabs the latest release of Winget from the Github API for the install process.
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop
$latestVersion = $response.tag_name #Stores version number of latest release.
$licenseWingetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*License1.xml"} #Index value for License file.
Write-Host "Latest Version:`t$($latestVersion)`n"
Write-Host "Downloading..."
$assetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"}
Invoke-WebRequest -Uri $licenseWingetUrl -OutFile $ENV:TEMP\License1.xml
# The only pain is that the msixbundle for winget-cli is 246MB. In some situations this can take a bit, with slower connections.
Invoke-WebRequest -Uri $assetUrl -OutFile $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle
}
Catch{
throw [WingetFailedInstall]::new('Failed to get latest Winget release and license')
}
$ProgressPreference = $PreviousProgressPreference
}
function Install-WinUtilWinget {
<#
.SYNOPSIS
Installs Winget if it is not already installed.
.DESCRIPTION
This function will download the latest version of Winget and install it. If Winget is already installed, it will do nothing.
#>
$isWingetInstalled = Test-WinUtilPackageManager -winget
Try {
if ($isWingetInstalled -eq "installed") {
Write-Host "`nWinget is already installed.`r" -ForegroundColor Green
return
} elseif ($isWingetInstalled -eq "outdated") {
Write-Host "`nWinget is Outdated. Continuing with install.`r" -ForegroundColor Yellow
} else {
Write-Host "`nWinget is not Installed. Continuing with install.`r" -ForegroundColor Red
}
# Gets the computer's information
if ($null -eq $sync.ComputerInfo){
$ComputerInfo = Get-ComputerInfo -ErrorAction Stop
} else {
$ComputerInfo = $sync.ComputerInfo
}
if (($ComputerInfo.WindowsVersion) -lt "1809") {
# Checks if Windows Version is too old for Winget
Write-Host "Winget is not supported on this version of Windows (Pre-1809)" -ForegroundColor Red
return
}
# Install Winget via GitHub method.
# Used part of my own script with some modification: ruxunderscore/windows-initialization
Write-Host "Downloading Winget Prerequsites`n"
Get-WinUtilWingetPrerequisites
Write-Host "Downloading Winget and License File`r"
Get-WinUtilWingetLatest
Write-Host "Installing Winget w/ Prerequsites`r"
Add-AppxProvisionedPackage -Online -PackagePath $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle -DependencyPackagePath $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx, $ENV:TEMP\Microsoft.UI.Xaml.x64.appx -LicensePath $ENV:TEMP\License1.xml
Write-Host "Manually adding Winget Sources, from Winget CDN."
Add-AppxPackage -Path https://cdn.winget.microsoft.com/cache/source.msix #Seems some installs of Winget don't add the repo source, this should makes sure that it's installed every time.
Write-Host "Winget Installed" -ForegroundColor Green
Write-Host "Enabling NuGet and Module..."
Install-PackageProvider -Name NuGet -Force
Install-Module -Name Microsoft.WinGet.Client -Force
# Winget only needs a refresh of the environment variables to be used.
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
} Catch {
Write-Host "Failure detected while installing via GitHub method. Continuing with Chocolatey method as fallback." -ForegroundColor Red
# In case install fails via GitHub method.
Try {
# Install Choco if not already present
Install-WinUtilChoco
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget-cli"
Write-Host "Winget Installed" -ForegroundColor Green
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
} Catch {
throw [WingetFailedInstall]::new('Failed to install!')
}
}
}
$isAdmin = [System.Security.Principal.WindowsPrincipal]::new(
[System.Security.Principal.WindowsIdentity]::GetCurrent()).
IsInRole('Administrators')
if(-not $isAdmin) {
$params = @{
FilePath = 'powershell' # or pwsh if Core
Verb = 'RunAs'
ArgumentList = @(
'-ExecutionPolicy ByPass'
'-File "{0}"' -f $PSCommandPath
)
}
Start-Process -Wait @params
Write-Host "Admin stuff done..."
} else {
Write-Host "In Admin stuff..."
Install-WinUtilWinget
return
}
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','chocolatey'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','Git.Git'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','Microsoft.WindowsTerminal'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','Python.Python.3.12'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','AntibodySoftware.WizFile'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','Kitware.CMake'
Start-Process -NoNewWindow -Wait winget -ArgumentList 'install','Microsoft.VCRedist.2015+.x64'
Start-Process -Verb RunAs -Wait powershell -argumentlist 'C:\ProgramData\chocolatey\bin\choco.exe','install','geany','geany-plugins','winlibs','conan','meson'

View file

@ -0,0 +1,43 @@
#version 330 core
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
uniform Material material;
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
uniform vec3 viewPos;
void main()
{
vec3 ambient = light.ambient * material.ambient;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * (diff * material.diffuse);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * (material.specular * spec);
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,16 @@
#version 330 core
out vec4 FragColor;
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
void main()
{
FragColor = vec4(light.diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,17 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
}

View file

@ -0,0 +1,46 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Light light;
uniform Material material;
void main()
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 ambient = light.ambient * mat_tex;
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * spec_tex;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,16 @@
#version 330 core
out vec4 FragColor;
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
void main()
{
FragColor = vec4(light.diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,67 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Light light;
uniform Material material;
void main()
{
vec3 lightDir = normalize(light.position - FragPos);
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 ambient = light.ambient * mat_tex;
vec3 norm = normalize(Normal);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * spec_tex;
// splotlight
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
// determine attenuation based on light distance
float distance = length(light.position - FragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,16 @@
#version 330 core
out vec4 FragColor;
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
void main()
{
FragColor = vec4(light.diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,150 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
#define NR_POINT_LIGHTS 4
uniform int pointLightCount;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform DirLight dirLight;
uniform SpotLight spotLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
return ambient + diffuse + specular;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 result = CalcDirLight(dirLight, norm, viewDir);
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
}
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,150 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
#define NR_POINT_LIGHTS 4
uniform int pointLightCount;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform DirLight dirLight;
uniform SpotLight spotLight;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
return ambient + diffuse + specular;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
vec3 result = CalcDirLight(dirLight, norm, viewDir);
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
}
result += CalcSpotLight(spotLight, norm, FragPos, viewDir);
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,162 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cut_off;
float outer_cut_off;
};
#define MAX_LIGHTS 4
uniform int pointLightCount = 0;
uniform PointLight pointLights[MAX_LIGHTS];
uniform int dirLightCount = 0;
uniform DirLight dirLights[MAX_LIGHTS];
uniform int spotLightCount = 0;
uniform SpotLight spotLights[MAX_LIGHTS];
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
return ambient + diffuse + specular;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cut_off - light.outer_cut_off;
float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// kick it off with the first dirlight
vec3 result = CalcDirLight(dirLights[0], norm, viewDir);
// then augment with more (off by one)
for(int i = 1; i < dirLightCount; i++) {
result += CalcDirLight(dirLights[i], norm, viewDir);
}
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
}
for(int i = 0; i < spotLightCount; i++) {
result += CalcSpotLight(spotLights[i], norm, FragPos, viewDir);
}
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,162 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cut_off;
float outer_cut_off;
};
#define MAX_LIGHTS 4
uniform int pointLightCount = 0;
uniform PointLight pointLights[MAX_LIGHTS];
uniform int dirLightCount = 0;
uniform DirLight dirLights[MAX_LIGHTS];
uniform int spotLightCount = 0;
uniform SpotLight spotLights[MAX_LIGHTS];
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
return ambient + diffuse + specular;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cut_off - light.outer_cut_off;
float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// kick it off with the first dirlight
vec3 result = CalcDirLight(dirLights[0], norm, viewDir);
// then augment with more (off by one)
for(int i = 1; i < dirLightCount; i++) {
result += CalcDirLight(dirLights[i], norm, viewDir);
}
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
}
for(int i = 0; i < spotLightCount; i++) {
result += CalcSpotLight(spotLights[i], norm, FragPos, viewDir);
}
FragColor = vec4(result, 1.0);
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,176 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cut_off;
float outer_cut_off;
};
#define MAX_LIGHTS 4
uniform int pointLightCount = 0;
uniform PointLight pointLights[MAX_LIGHTS];
uniform int dirLightCount = 0;
uniform DirLight dirLights[MAX_LIGHTS];
uniform int spotLightCount = 0;
uniform SpotLight spotLights[MAX_LIGHTS];
float near = 0.1;
float far = 100.0;
vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
return ambient + diffuse + specular;
}
vec3 CalcPointLight(PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec3 CalcSpotLight(SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 mat_tex = vec3(texture(material.diffuse, TexCoords));
vec3 spec_tex = vec3(texture(material.specular, TexCoords));
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec3 ambient = light.ambient * mat_tex;
vec3 diffuse = light.diffuse * diff * mat_tex;
vec3 specular = light.specular * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cut_off - light.outer_cut_off;
float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
float LinearizeDepth(float depth)
{
float ndc = depth * 2.0 - 1.0;
return (2.0 * near * far) / (far + near - ndc * (far - near));
}
void main()
{
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// kick it off with the first dirlight
vec3 result = CalcDirLight(dirLights[0], norm, viewDir);
// then augment with more (off by one)
for(int i = 1; i < dirLightCount; i++) {
result += CalcDirLight(dirLights[i], norm, viewDir);
}
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(pointLights[i], norm, FragPos, viewDir);
}
for(int i = 0; i < spotLightCount; i++) {
result += CalcSpotLight(spotLights[i], norm, FragPos, viewDir);
}
FragColor = vec4(result, 1.0);
// float depth = LinearizeDepth(gl_FragCoord.z) / far;
// FragColor = vec4(vec3(depth), 1.0);
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,6 @@
#version 330 core
out vec4 FragColor;
void main() {
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,168 @@
#version 330 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
uniform vec3 viewPos;
uniform Material material;
struct DirLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 direction;
vec3 position;
vec3 diffuse;
vec3 specular;
vec3 ambient;
float constant;
float linear;
float quadratic;
float cut_off;
float outer_cut_off;
};
#define MAX_LIGHTS 4
uniform int pointLightCount = 0;
uniform PointLight pointLights[MAX_LIGHTS];
uniform int dirLightCount = 0;
uniform DirLight dirLights[MAX_LIGHTS];
uniform int spotLightCount = 0;
uniform SpotLight spotLights[MAX_LIGHTS];
float near = 0.1;
float far = 100.0;
vec4 CalcDirLight(vec4 mat_tex, vec4 spec_tex, DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
return ambient + diffuse + specular;
}
vec4 CalcPointLight(vec4 mat_tex, vec4 spec_tex, PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
vec4 CalcSpotLight(vec4 mat_tex, vec4 spec_tex, SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
vec4 ambient = vec4(light.ambient, 1.0) * mat_tex;
vec4 diffuse = vec4(light.diffuse, 1.0) * diff * mat_tex;
vec4 specular = vec4(light.specular, 1.0) * spec * spec_tex;
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cut_off - light.outer_cut_off;
float intensity = clamp((theta - light.outer_cut_off) / epsilon, 0.0, 1.0);
diffuse *= intensity;
specular *= intensity;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return ambient + diffuse + specular;
}
float LinearizeDepth(float depth)
{
float ndc = depth * 2.0 - 1.0;
return (2.0 * near * far) / (far + near - ndc * (far - near));
}
void main()
{
vec4 mat_tex = texture(material.diffuse, TexCoords);
vec4 spec_tex = texture(material.specular, TexCoords);
vec3 norm = normalize(Normal);
vec3 viewDir = normalize(viewPos - FragPos);
// kick it off with the first dirlight
vec4 result = CalcDirLight(mat_tex, spec_tex, dirLights[0], norm, viewDir);
// then augment with more (off by one)
for(int i = 1; i < dirLightCount; i++) {
result += CalcDirLight(mat_tex, spec_tex, dirLights[i], norm, viewDir);
}
for(int i = 0; i < pointLightCount; i++) {
result += CalcPointLight(mat_tex, spec_tex, pointLights[i], norm, FragPos, viewDir);
}
for(int i = 0; i < spotLightCount; i++) {
result += CalcSpotLight(mat_tex, spec_tex, spotLights[i], norm, FragPos, viewDir);
}
FragColor = result;
}

View file

@ -0,0 +1,9 @@
#version 330 core
out vec4 FragColor;
uniform vec3 diffuse;
void main()
{
FragColor = vec4(diffuse, 1.0); // set all 4 vector values to 1.0
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,11 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoords);
}

View file

@ -0,0 +1,20 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,38 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
const float offset = 1.0 / 300.0;
void main()
{
vec2 offsets[9] = vec2[](
vec2(-offset, offset), // top-left
vec2( 0.0f, offset), // top-center
vec2( offset, offset), // top-right
vec2(-offset, 0.0f), // center-left
vec2( 0.0f, 0.0f), // center-center
vec2( offset, 0.0f), // center-right
vec2(-offset, -offset), // bottom-left
vec2( 0.0f, -offset), // bottom-center
vec2( offset, -offset) // bottom-right
);
float kernel[9] = float[](
1.0 / 16, 2.0 / 16, 1.0 / 16,
2.0 / 16, 4.0 / 16, 2.0 / 16,
1.0 / 16, 2.0 / 16, 1.0 / 16
);
vec3 col = vec3(0.0);
for(int i = 0; i < 9; i++) {
vec3 sampleTex = vec3(texture(screenTexture, TexCoords.st + offsets[i]));
col += sampleTex * kernel[i];
}
FragColor = vec4(col, 1.0);
}

View file

@ -0,0 +1,11 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoords;
uniform sampler2D screenTexture;
void main()
{
FragColor = texture(screenTexture, TexCoords);
}

View file

@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;
out vec2 TexCoords;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,17 @@
#version 330 core
out vec4 FragColor;
in vec3 Normal;
in vec3 FragPos;
in vec2 TexCoords;
uniform vec3 cameraPos;
uniform samplerCube skybox;
void main()
{
float ratio = 1.0/1.52;
vec3 I = normalize(FragPos - cameraPos);
vec3 R = refract(I, normalize(Normal), ratio);
FragColor = vec4(texture(skybox, R).rgb, 1.0);
}

View file

@ -0,0 +1,11 @@
#version 330 core
out vec4 FragColor;
in vec3 TexCoords;
uniform samplerCube skybox;
void main()
{
FragColor = texture(skybox, TexCoords);
}

View file

@ -0,0 +1,14 @@
#version 330 core
layout (location = 0) in vec3 aPos;
out vec3 TexCoords;
uniform mat4 projection;
uniform mat4 view;
void main()
{
TexCoords = aPos;
vec4 pos = projection * view * vec4(aPos, 1.0);
gl_Position = pos.xyww;
}

View file

@ -0,0 +1,21 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
out vec3 Position;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
Normal = mat3(transpose(inverse(model))) * aNormal;
FragPos = vec3(model * vec4(aPos, 1.0));
gl_Position = projection * view * vec4(FragPos, 1.0);
TexCoords = aTexCoords;
}

View file

@ -0,0 +1,8 @@
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
void main()
{
FragColor = vec4(ourColor, 1.0);
}

View file

@ -0,0 +1,11 @@
#version 330 core
layout (location = 0) in vec3 aPos; // the position variable has attribute position 0
layout (location = 1) in vec3 aColor;
out vec3 ourColor;
void main()
{
gl_Position = vec4(aPos, 1.0); // see how we directly give a vec3 to vec4's constructor
ourColor = aColor;
}

View file

@ -0,0 +1,11 @@
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
uniform sampler2D texture1;
void main()
{
FragColor = texture(texture1, TexCoord);
}

View file

@ -0,0 +1,15 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 TexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
gl_Position = projection * view * model * vec4(aPos, 1.0f);
TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

View file

@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

View file

@ -0,0 +1,70 @@
#include "camera.hpp"
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
glm::mat4 Camera::look_at() {
return glm::lookAt(position, position + front, up);
}
void Camera::forward() {
dirty = true;
position += speed * front;
}
void Camera::back() {
dirty = true;
position -= speed * front;
}
void Camera::left() {
dirty = true;
position -= glm::normalize(glm::cross(front, up)) * speed;
}
void Camera::right() {
dirty = true;
position += glm::normalize(glm::cross(front, up)) * speed;
}
void Camera::update(float deltaTime) {
speed = movement_speed * deltaTime;
}
void Camera::mouse_move(double xpos, double ypos) {
dirty = true;
if(firstMouse) {
lastX = xpos;
lastY = ypos;
firstMouse = false;
}
float xoffset = xpos - lastX;
float yoffset = lastY - ypos;
lastX = xpos;
lastY = ypos;
const float sensitivity = 0.1f;
xoffset *= sensitivity;
yoffset *= sensitivity;
yaw += xoffset;
pitch += yoffset;
if(pitch > 89.0f) pitch = 89.0f;
if(pitch < -89.0f) pitch = -89.0f;
direction.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
direction.y = sin(glm::radians(pitch));
direction.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
front = glm::normalize(direction);
}
void Camera::mouse_scroll(double xoffset, double yoffset) {
dirty = true;
fov -= (float)yoffset;
if(fov < 1.0f) fov = 1.0f;
if(fov > 90.0f) fov = 90.0f;
}

View file

@ -0,0 +1,28 @@
#pragma once
#include <glm/glm.hpp>
struct Camera {
glm::vec3 position{0.0f, 0.0f, 3.0f};
glm::vec3 front{0.0f, 0.0f, -1.0f};
glm::vec3 up{0.0f, 1.0f, 0.0f};
glm::vec3 direction{0.0f, 0.0f, 0.0f};
float movement_speed = 20.0f;
float pitch = 0.0f;
float yaw = -90.0f;
float speed = 0.05f;
float lastX = 400;
float lastY = 300;
float fov = 45.0f;
bool firstMouse = true;
bool dirty = true;
glm::mat4 look_at();
void forward();
void back();
void left();
void right();
void update(float deltaTime);
void mouse_move(double xpos, double ypos);
void mouse_scroll(double xoffset, double yoffset);
};

View file

@ -0,0 +1,117 @@
#pragma once
#include <glm/glm.hpp>
#include <vector>
#include <unordered_map>
#include "json.hpp"
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
#define MAX_LIGHTS 4
namespace components {
template <typename T> struct NameOf;
struct Material {
glm::vec3 ambient{0.1f,0.1f,0.1f};
float shininess{32.0f};
unsigned int diffuseMap = 0;
unsigned int specularMap = 0;
};
ENROLL_COMPONENT(Material, ambient, shininess, diffuseMap, specularMap);
struct Light {
glm::vec3 position{0.0f, 0.0f, 0.0f};
glm::vec3 direction{0.0f, 0.0f, 0.0f};
glm::vec3 ambient{0.0f, 0.0f, 0.0f};
glm::vec3 diffuse{0.0f, 0.0f, 0.0f};
glm::vec3 specular{0.0f, 0.0f, 0.0f};
float constant=0.0f;
float linear=0.0f;
float quadratic=0.0f;
float cut_off=0.0f;
float outer_cut_off=0.0f;
bool on=true;
void adjust(float amount) {
ambient += amount;
diffuse += amount;
specular += amount;
}
};
ENROLL_COMPONENT(Light,
position, direction,
ambient, diffuse, specular,
constant, linear, quadratic,
cut_off, outer_cut_off, on);
struct Lighting {
std::vector<Light> directional;
std::vector<Light> positioned;
std::vector<Light> spot;
Light camera;
};
ENROLL_COMPONENT(Lighting, directional, positioned, spot, camera);
struct Camera {
glm::vec3 position{0.0f, 0.0f, 3.0f};
glm::vec3 front{0.0f, 0.0f, -1.0f};
glm::vec3 up{0.0f, 1.0f, 0.0f};
glm::vec3 direction{0.0f, 0.0f, 0.0f};
float movement_speed = 20.0f;
};
ENROLL_COMPONENT(Camera, position, front, up, direction, movement_speed);
struct Model {
std::string directory;
std::string model_path;
};
ENROLL_COMPONENT(Model, directory, model_path);
using Position = glm::vec3;
struct Rotation {
float angle = 0;
glm::vec3 axes{1.0f, 0.0f, 0.0f};
};
ENROLL_COMPONENT(Rotation, angle, axes);
struct Thing {
std::string model;
std::string material;
Position position;
Rotation rotation;
float scale;
};
ENROLL_COMPONENT(Thing, model, material, position, rotation, scale);
struct Shader {
std::string vertex_path;
std::string frag_path;
};
ENROLL_COMPONENT(Shader, vertex_path, frag_path);
struct Scene {
components::Shader shader;
components::Shader reflect_shader;
components::Shader screen_shader;
components::Shader skybox_shader;
std::vector<std::string> skybox_faces;
std::unordered_map<std::string, Material> materials;
std::unordered_map<std::string, Model> models;
std::vector<Thing> things;
Camera camera;
Lighting light;
};
ENROLL_COMPONENT(Scene, shader, reflect_shader, screen_shader, skybox_shader, skybox_faces, materials, models, things, camera, light);
}

View file

@ -0,0 +1,47 @@
#include "dbc.hpp"
#include <iostream>
void dbc::log(const string &message, const std::source_location location) {
std::cout << '[' << location.file_name() << ':'
<< location.line() << "|"
<< location.function_name() << "] "
<< message << std::endl;
}
void dbc::sentinel(const string &message, const std::source_location location) {
string err = $F("[SENTINEL!] {}", message);
dbc::log(err, location);
throw dbc::SentinelError(err);
}
void dbc::pre(const string &message, bool test, const std::source_location location) {
if(!test) {
string err = $F("[PRE!] {}", message);
dbc::log(err, location);
throw dbc::PreCondError(err);
}
}
void dbc::pre(const string &message, std::function<bool()> tester, const std::source_location location) {
dbc::pre(message, tester(), location);
}
void dbc::post(const string &message, bool test, const std::source_location location) {
if(!test) {
string err = $F("[POST!] {}", message);
dbc::log(err, location);
throw dbc::PostCondError(err);
}
}
void dbc::post(const string &message, std::function<bool()> tester, const std::source_location location) {
dbc::post(message, tester(), location);
}
void dbc::check(bool test, const string &message, const std::source_location location) {
if(!test) {
string err = $F("[CHECK!] {}\n", message);
dbc::log(err, location);
throw dbc::CheckError(err);
}
}

View file

@ -0,0 +1,46 @@
#pragma once
#include <string>
#include <fmt/core.h>
#include <functional>
#include <source_location>
// AKA the Fuckit macro
#define $F(FMT, ...) fmt::format(FMT, ##__VA_ARGS__)
namespace dbc {
using std::string;
using CheckError = std::runtime_error;
using SentinelError = std::runtime_error;
using PreCondError = std::runtime_error;
using PostCondError = std::runtime_error;
void log(const string &message,
const std::source_location location =
std::source_location::current());
[[noreturn]] void sentinel(const string &message,
const std::source_location location =
std::source_location::current());
void pre(const string &message, bool test,
const std::source_location location =
std::source_location::current());
void pre(const string &message, std::function<bool()> tester,
const std::source_location location =
std::source_location::current());
void post(const string &message, bool test,
const std::source_location location =
std::source_location::current());
void post(const string &message, std::function<bool()> tester,
const std::source_location location =
std::source_location::current());
void check(bool test, const string &message,
const std::source_location location =
std::source_location::current());
}

View file

@ -0,0 +1,59 @@
#include "framebuffer.hpp"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
void FrameBuffer::init() {
// target_fb config
glGenFramebuffers(1, &target_fb);
glBindFramebuffer(GL_FRAMEBUFFER, target_fb);
// target_fb configuration
// -------------------------
glGenFramebuffers(1, &target_fb);
glBindFramebuffer(GL_FRAMEBUFFER, target_fb);
// create a color attachment texture
glGenTextures(1, &texture_buffer);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_buffer, 0);
// create a renderbuffer object for depth and stencil attachment (we won't be sampling these)
glGenRenderbuffers(1, &target_rbo);
glBindRenderbuffer(GL_RENDERBUFFER, target_rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, SCR_WIDTH, SCR_HEIGHT); // use a single renderbuffer object for both a depth AND stencil buffer.
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, target_rbo); // now actually attach it
// now that we actually created the target_fb and added all attachments we want to check if it is actually complete now
dbc::check(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE, "Frame buffer not complete.");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBuffer::begin() {
// target_fb stuff here
glBindFramebuffer(GL_FRAMEBUFFER, target_fb);
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void FrameBuffer::commit() {
// disable the frame buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
void FrameBuffer::draw(Screen& screen) {
glDisable(GL_DEPTH_TEST);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// render the screen quad
screen.shader.use();
glBindVertexArray(screen.target_VAO);
glBindTexture(GL_TEXTURE_2D, texture_buffer);
glDrawArrays(GL_TRIANGLES, 0, 6);
}

View file

@ -0,0 +1,15 @@
#pragma once
#include "shader.hpp"
#include "screen.hpp"
struct FrameBuffer {
unsigned int target_fb = 0;
unsigned int target_rbo = 0;
unsigned int texture_buffer = 0;
void init();
void begin();
void commit();
void draw(Screen& screen);
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,59 @@
#pragma once
#include <nlohmann/json.hpp>
#include <nlohmann/json_fwd.hpp>
#include <optional>
#include <glm/glm.hpp>
#include <vector>
#define ENROLL_COMPONENT(COMPONENT, ...) \
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(COMPONENT, __VA_ARGS__); \
template <> struct NameOf<COMPONENT> { \
static constexpr const char *name = #COMPONENT; \
};
// partial specialization (full specialization works too)
namespace nlohmann {
template <>
struct adl_serializer<glm::vec3> {
static void to_json(json& j, const glm::vec3& opt) {
}
static void from_json(const json& j, glm::vec3& opt) {
opt = glm::vec3(j[0], j[1], j[2]);
}
};
template <typename T>
struct adl_serializer<std::optional<T>> {
static void to_json(json& j, const std::optional<T>& opt) {
if (opt == std::nullopt) {
j = nullptr;
} else {
j = *opt; // this will call adl_serializer<T>::to_json which will
// find the free function to_json in T's namespace!
}
}
static void from_json(const json& j, std::optional<T>& opt) {
if (j.is_null() || j == false) {
opt = std::nullopt;
} else {
opt = std::make_optional<T>(j.template get<T>());
// same as above, but with adl_serializer<T>::from_json
}
}
};
template<>
struct adl_serializer<std::chrono::milliseconds> {
static void to_json(json& j, const std::chrono::milliseconds& opt) {
j = opt.count();
}
static void from_json(const json& j, std::chrono::milliseconds& opt) {
opt = std::chrono::milliseconds{int(j)};
}
};
}

View file

@ -0,0 +1,152 @@
#define _USE_MATH_DEFINES
#include <stb_image.h>
#include "scene.hpp"
#include "utils.hpp"
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void init_glfw() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
}
void framebuffer_size_callback(GLFWwindow *, int width, int height) {
glViewport(0, 0, width, height);
}
void mouse_callback(GLFWwindow *window, double xpos, double ypos) {
Scene* scene = static_cast<Scene*>(glfwGetWindowUserPointer(window));
scene->camera.mouse_move(xpos, ypos);
}
void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) {
Scene* scene = static_cast<Scene*>(glfwGetWindowUserPointer(window));
scene->camera.mouse_scroll(xoffset, yoffset);
}
GLFWwindow* create_window() {
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
dbc::check(window != NULL, "failed to open window");
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
auto good = gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
dbc::check(good, "failed to load GLAD");
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
return window;
}
void process_input(GLFWwindow *window, Scene& scene) {
if(glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
glfwSetWindowShouldClose(window, true);
}
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
scene.camera.forward();
}
if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
scene.camera.back();
}
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
scene.camera.left();
}
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
scene.camera.right();
}
if(glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
scene.reflect_on = !scene.reflect_on;
}
if(glfwGetKey(window, GLFW_KEY_M) == GLFW_PRESS) {
components::Rotation rotation{90.0f, {1.0f, 0.0f, 0.0f}};
scene.spawn("grass", scene.camera.position, rotation);
}
if(glfwGetKey(window, GLFW_KEY_L) == GLFW_PRESS) {
scene.light.camera.on = !scene.light.camera.on;
scene.shader.apply_lighting(scene.light);
}
if(glfwGetKey(window, GLFW_KEY_O) == GLFW_PRESS) {
for(auto& light : scene.light.directional) {
light.adjust(-0.01f);
}
scene.shader.apply_lighting(scene.light);
}
if(glfwGetKey(window, GLFW_KEY_P) == GLFW_PRESS) {
for(auto& light : scene.light.directional) {
light.adjust(0.01f);
}
scene.shader.apply_lighting(scene.light);
}
}
Scene setup() {
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glEnable(GL_CULL_FACE);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glDepthFunc(GL_LESS);
components::Scene config = utils::load_scene_config("config.json");
Scene scene(config);
return scene;
}
void update(GLFWwindow* window, Scene& scene) {
glfwPollEvents();
process_input(window, scene);
scene.update();
}
void render(GLFWwindow* window, Scene& scene) {
scene.render(window);
glfwSwapBuffers(window);
}
void quit(GLFWwindow* window, Scene& scene) {
scene.cleanup();
glfwTerminate();
}
int main() {
init_glfw();
auto window = create_window();
auto scene = setup();
glfwSetWindowUserPointer(window, &scene);
while(!glfwWindowShouldClose(window)) {
update(window, scene);
render(window, scene);
}
quit(window, scene);
return 0;
}

View file

@ -0,0 +1,49 @@
#include "mesh.hpp"
#include "dbc.hpp"
void Mesh::draw(Shader &shader, bool with_textures) {
if(with_textures) {
apply_textures(shader);
}
glBindVertexArray(VAO);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0);
}
void Mesh::apply_textures(const Shader& shader) {
for(unsigned int i = 0; i < textures.size(); i++) {
Texture& texture = textures[i];
texture.uniform_id = glGetUniformLocation(shader.ID, texture.target.c_str());
glActiveTexture(GL_TEXTURE0 + i);
// move this to setup_mesh
glUniform1i(texture.uniform_id, i);
glBindTexture(GL_TEXTURE_2D, texture.id);
}
}
void Mesh::setup_mesh() {
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
// this matches the locations in the vertex shader
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, tex_coords));
}

View file

@ -0,0 +1,72 @@
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "shader.hpp"
#include <string>
#include <vector>
struct Vertex {
glm::vec3 position;
glm::vec3 normal;
glm::vec2 tex_coords;
};
struct TextureCounts {
unsigned int diffuseNr = 1;
unsigned int specularNr = 1;
unsigned int normalNr = 1;
unsigned int heightNr = 1;
};
struct Texture {
unsigned int id;
std::string type;
std::string path;
std::string target;
int uniform_id=-1;
Texture(unsigned int id, const std::string& type, const std::string& path, TextureCounts& count) :
id(id), type(type)
{
unsigned int number = 0;
if(type == "texture_diffuse") {
number = count.diffuseNr++;
} else if(type == "texture_specular") {
number = count.specularNr++;
} else if(type == "texture_normal") {
number = count.normalNr++;
} else if(type == "texture_height") {
number = count.heightNr++;
} else {
dbc::sentinel($F("Invalid texture type={} for file={}", type, path));
}
target = std::format("{}{}", type, number);
}
};
struct Mesh {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
unsigned int VAO = 0;
unsigned int VBO = 0;
unsigned int EBO = 0;
Mesh(std::vector<Vertex>& vertices, std::vector<unsigned int>& indices, std::vector<Texture>& textures) :
vertices(vertices),
indices(indices),
textures(textures)
{
setup_mesh();
}
void draw(Shader &shader, bool with_textures);
void setup_mesh();
void apply_textures(const Shader& shader);
};

View file

@ -0,0 +1,213 @@
#include "model.hpp"
#include "dbc.hpp"
#include <print>
unsigned int texture_from_file(const std::string& directory, const std::string& path);
unsigned int texture_from_internal(const aiScene *scene, size_t index);
unsigned int image_to_texture(unsigned char *data, int width, int height, int nrComponents) {
unsigned int textureID;
glGenTextures(1, &textureID);
GLenum format = GL_RGB;
switch(nrComponents) {
case 1:
format = GL_RED;
break;
case 3:
format = GL_RGB;
break;
case 4:
format = GL_RGBA;
break;
default:
dbc::sentinel($F("Impossible nrComponents={} when loading image", nrComponents));
}
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return textureID;
}
unsigned int texture_from_internal(const aiScene *scene, size_t index) {
const aiTexture *aiTex = scene->mTextures[index];
unsigned int textureID = 0;
int width = 0;
int height = 0;
int nrComponents = 0;
unsigned char *data = nullptr;
const unsigned char* dataBytes = (const unsigned char*)aiTex->pcData;
if(aiTex->mHeight == 0) {
// compressed texture (PNG or JPG)
size_t dataSize = aiTex->mWidth;
data = stbi_load_from_memory(dataBytes, dataSize, &width, &height, &nrComponents, 0);
textureID = image_to_texture(data, width, height, nrComponents);
stbi_image_free(data);
} else {
data = (unsigned char*)aiTex->pcData;
width = aiTex->mWidth;
height = aiTex->mHeight;
nrComponents = 4; // either BGRA8888 or RGBA8888
textureID = image_to_texture(data, width, height, nrComponents);
}
return textureID;
}
unsigned int texture_from_file(const std::string& directory, const std::string& path)
{
std::string filename = directory + "/" + path;
int width = 0;
int height = 0;
int nrComponents = 0;
unsigned char *data = stbi_load(filename.c_str(), &width, &height, &nrComponents, 0);
dbc::check(data != nullptr, $F("Failed to load texture {}", filename));
unsigned int textureID = image_to_texture(data, width, height, nrComponents);
stbi_image_free(data);
return textureID;
}
void Model::draw(Shader &shader, bool with_textures) {
for(auto& mesh : meshes) {
mesh.draw(shader, with_textures);
}
}
void Model::load_model() {
std::string path = directory + "/" + model_path;
Assimp::Importer importer;
const aiScene* scene = importer.ReadFile(path,
aiProcess_Triangulate |
aiProcess_GenSmoothNormals |
aiProcess_FlipUVs |
aiProcess_CalcTangentSpace);
dbc::check(scene != nullptr, "Assimp ReadFile return null");
dbc::check(!(scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE), "Assimp says incomplete.");
dbc::check(scene->mRootNode != nullptr, "Assimp loaded scene doesn't have a root node");
process_node(scene, scene->mRootNode);
}
void Model::process_node(const aiScene *scene, aiNode *node) {
for(unsigned int i = 0; i < node->mNumMeshes; i++) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
meshes.push_back(process_mesh(scene, mesh));
}
for(unsigned int i = 0; i < node->mNumChildren; i++) {
process_node(scene, node->mChildren[i]);
}
}
Mesh Model::process_mesh(const aiScene *scene, aiMesh *mesh) {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture> textures;
for(unsigned int i = 0; i < mesh->mNumVertices; i++) {
glm::vec3 position{
mesh->mVertices[i].x,
mesh->mVertices[i].y,
mesh->mVertices[i].z};
glm::vec3 normal{};
glm::vec2 tex_coords{0.0f, 0.0f};
if(mesh->HasNormals()) {
normal = glm::vec3(
mesh->mNormals[i].x,
mesh->mNormals[i].y,
mesh->mNormals[i].z);
}
if(mesh->mTextureCoords[0]) {
tex_coords = glm::vec2(
mesh->mTextureCoords[0][i].x,
mesh->mTextureCoords[0][i].y
);
}
vertices.emplace_back(position, normal, tex_coords);
}
for(unsigned int i = 0; i < mesh->mNumFaces; i++) {
aiFace& face = mesh->mFaces[i];
for(unsigned int j = 0; j < face.mNumIndices; j++) {
indices.emplace_back(face.mIndices[j]);
}
}
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
// we assume a convention for sampler names in the shaders. Each diffuse texture should be named
// as 'texture_diffuseN' where N is a sequential number ranging from 1 to MAX_SAMPLER_NUMBER.
// Same applies to other texture as the following list summarizes:
// diffuse: texture_diffuseN
// specular: texture_specularN
// normal: texture_normalN
// 1. diffuse maps
load_material_textures(scene, textures, material, aiTextureType_DIFFUSE, "texture_diffuse");
// 2. specular maps
load_material_textures(scene, textures, material, aiTextureType_SPECULAR, "texture_specular");
// 3. normal maps
load_material_textures(scene, textures, material, aiTextureType_HEIGHT, "texture_normal");
// 4. height maps
load_material_textures(scene, textures, material, aiTextureType_AMBIENT, "texture_height");
return Mesh(vertices, indices, textures);
}
void Model::load_material_textures(const aiScene *scene, std::vector<Texture>& textures, aiMaterial *mat, aiTextureType type, std::string type_name)
{
for(unsigned int i = 0; i < mat->GetTextureCount(type); i++) {
aiString str;
mat->GetTexture(type, i, &str);
std::string tx_path{str.C_Str()};
dbc::check(!tx_path.empty(), "Texture has empty path, should be impossible?");
if(textures_loaded.contains(tx_path)) {
textures.push_back(textures_loaded.at(tx_path));
} else {
unsigned int tx_id = 0;
// if it's a *# style path then it's internal
if(tx_path[0] == '*') {
// get the texture from the internal version
tx_id = texture_from_internal(scene, std::stoi(tx_path.substr(1)));
} else {
// else get it from a file
tx_id = texture_from_file(directory, tx_path);
}
// dubious code here, but seems to be right
auto& result = textures.emplace_back(tx_id, type_name, tx_path, texture_counts);
textures_loaded.try_emplace(tx_path, result);
}
}
}

View file

@ -0,0 +1,42 @@
#pragma once
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <stb_image.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <mesh.hpp>
#include <shader.hpp>
#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>
#include <map>
#include <vector>
struct Model {
std::string directory;
std::string model_path;
std::map<std::string, Texture> textures_loaded;
std::vector<Mesh> meshes;
TextureCounts texture_counts;
bool gammaCorrection;
Model(const std::string& directory, const std::string& model_path) :
directory(directory), model_path(model_path)
{
load_model();
}
void draw(Shader &shader, bool with_textures=true);
void load_model();
void process_node(const aiScene *scene, aiNode *node);
Mesh process_mesh(const aiScene *scene, aiMesh *mesh);
void load_material_textures(const aiScene *scene, std::vector<Texture>& textures, aiMaterial *mat, aiTextureType type, std::string typeName);
};

View file

@ -0,0 +1,136 @@
#include "scene.hpp"
#include "dbc.hpp"
#include <math.h>
#include "skybox.hpp"
void Scene::update() {
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// for now just detect the camera moved and do spotlight update
if(camera.dirty) {
light.camera.position = camera.position;
light.camera.direction = camera.front;
// just update the camera's light
shader.apply_spot_light(light.camera, 0);
camera.dirty = false;
}
camera.update(deltaTime);
}
void Scene::draw_thing(Shader& with_shader, Thing& thing)
{
with_shader.apply_material(thing.material);
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, thing.position);
model = glm::rotate(model, glm::radians(thing.rotation.angle), thing.rotation.axes);
model = glm::scale(model, glm::vec3(thing.scale));
with_shader.setMat4("model", model);
// !reflect_on turns it on? yeah weird
thing.model.draw(with_shader, !reflect_on);
}
void Scene::render(GLFWwindow* window) {
glm::mat4 view = camera.look_at();
glm::mat4 projection = glm::mat4(1.0f);
auto& with_shader = reflect_on ? reflect_shader : shader;
// fov, aspect, near plane, far plane
projection = glm::perspective(glm::radians(camera.fov), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f);
framebuffer.begin();
// render the scene
with_shader.use();
with_shader.setMat4("view", view);
with_shader.setMat4("projection", projection);
with_shader.setVec3("cameraPos", camera.position);
for(auto& thing : things) {
draw_thing(with_shader, thing);
}
render_skybox(projection);
framebuffer.commit();
framebuffer.draw(screen);
}
void Scene::cleanup() {
shader.cleanup();
}
void Scene::spawn(const std::string& name, components::Position& position, components::Rotation& rotation) {
if(models.contains(name)) {
things.emplace_back(
name,
models.at(name),
materials.at("default"),
position,
rotation,
1.0f);
} else {
dbc::log($F("No model named: {}", name));
}
}
void Scene::init_skybox() {
glGenVertexArrays(1, &skyboxVAO);
glGenBuffers(1, &skyboxVBO);
glBindVertexArray(skyboxVAO);
glBindBuffer(GL_ARRAY_BUFFER, skyboxVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(skyboxVertices), &skyboxVertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
load_skybox_textures();
}
void Scene::load_skybox_textures() {
int width = 0;
int height = 0;
int nrChannels = 0;
size_t face_i = 0;
glGenTextures(1, &skybox_texture_id);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_texture_id);
for(const auto& face : skybox_faces) {
unsigned char *data = stbi_load(face.c_str(), &width, &height, &nrChannels, 0);
dbc::check(data != nullptr, $F("Failed to load skybox face {}", face));
dbc::check(nrChannels == 3, $F("Skybox face {} must be RGB but you have {} channels", face, nrChannels));
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face_i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
face_i++;
stbi_image_free(data);
}
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
}
void Scene::render_skybox(const glm::mat4& projection) {
glDepthFunc(GL_LEQUAL);
skybox_shader.use();
glm::mat4 view = glm::mat4(glm::mat3(camera.look_at()));
skybox_shader.setMat4("view", view);
skybox_shader.setMat4("projection", projection);
glBindVertexArray(skyboxVAO);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_texture_id);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glDepthFunc(GL_LESS);
}

View file

@ -0,0 +1,98 @@
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include "shader.hpp"
#include "model.hpp"
#include "shader.hpp"
#include "model.hpp"
#include "camera.hpp"
#include "components.hpp"
#include "framebuffer.hpp"
#include <vector>
#include <unordered_map>
struct Thing {
std::string name;
Model& model;
Material& material;
components::Position position;
components::Rotation rotation;
float scale;
float distance = 0;
};
struct Scene {
Shader shader;
Shader reflect_shader;
Shader skybox_shader;
std::vector<std::string> skybox_faces;
Screen screen;
FrameBuffer framebuffer;
std::unordered_map<std::string, components::Material> materials;
Camera camera;
components::Lighting light;
std::unordered_map<std::string, Model> models;
std::vector<Thing> things;
float deltaTime = 0.0f;
float lastFrame = 0.0f;
unsigned int skyboxVAO = 0;
unsigned int skyboxVBO = 0;
unsigned int skybox_texture_id = 0;
bool reflect_on = false;
Scene(components::Scene& config):
shader{config.shader.vertex_path, config.shader.frag_path},
reflect_shader{config.reflect_shader.vertex_path, config.reflect_shader.frag_path},
skybox_shader{config.skybox_shader.vertex_path, config.skybox_shader.frag_path},
skybox_faces{config.skybox_faces},
screen{.shader={config.screen_shader.vertex_path, config.screen_shader.frag_path}},
materials{config.materials},
camera{
.position=config.camera.position,
.front=config.camera.front,
.up=config.camera.up,
.direction=config.camera.direction,
.movement_speed=config.camera.movement_speed,
},
light{config.light}
{
for(auto& [name, model] : config.models) {
models.try_emplace(name, model.directory, model.model_path);
}
for(auto& thing : config.things) {
things.emplace_back(
thing.model,
models.at(thing.model),
materials.at(thing.material),
thing.position,
thing.rotation,
thing.scale);
}
shader.use();
shader.setInt("texture1", 0);
shader.apply_lighting(light);
skybox_shader.use();
skybox_shader.setInt("skybox", 0);
framebuffer.init();
screen.init();
init_skybox();
}
void update();
void draw_thing(Shader& with_shader, Thing& thing);
void render(GLFWwindow* window);
void cleanup();
void spawn(const std::string& name, components::Position& position, components::Rotation& rotation);
void init_skybox();
void load_skybox_textures();
void render_skybox(const glm::mat4& projection);
};

View file

@ -0,0 +1,18 @@
#include "screen.hpp"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
void Screen::init() {
shader.use();
shader.setInt("screenTexture", 0);
glGenVertexArrays(1, &target_VAO);
glGenBuffers(1, &target_VBO);
glBindVertexArray(target_VAO);
glBindBuffer(GL_ARRAY_BUFFER, target_VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void *)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "shader.hpp"
struct Screen {
Shader shader;
unsigned int target_VAO = 0;
unsigned int target_VBO = 0;
float vertices[24] = {
// vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates.
// positions // texCoords
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, -1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f
};
void init();
};

View file

@ -0,0 +1,206 @@
#include "shader.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include <print>
#include <filesystem>
#include "dbc.hpp"
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
namespace fs = std::filesystem;
inline std::string read_file(const std::string& filename) {
// load the file
std::ifstream in_file{filename, std::ios::binary};
// get the size of the file
std::stringstream in_str;
in_str << in_file.rdbuf();
return in_str.str();
}
void check_error(const std::string& what, unsigned int thing, GLenum check_type) {
int success = 0;
char infoLog[512] = {0};
if(check_type == GL_LINK_STATUS) {
glGetProgramiv(thing, check_type, &success);
if(!success) {
glGetProgramInfoLog(thing, 512, NULL, infoLog);
dbc::sentinel(std::format("ERROR: Program {} compile failed: {}", what, infoLog));
}
} else {
glGetShaderiv(thing, check_type, &success);
if(!success) {
glGetShaderInfoLog(thing, 512, NULL, infoLog);
dbc::sentinel(std::format("ERROR: Shader {} compile failed: {}", what, infoLog));
}
}
}
unsigned int Shader::load_shader(const std::string& filename, GLenum shader_type) {
dbc::log($F("Loading shader {}", filename));
dbc::check(fs::exists(filename),
std::format("shader file {} does not exist", filename));
// create the shader
std::string shader_code = read_file(filename);
const char* shader_code_ptr = shader_code.c_str();
int shader_id = glCreateShader(shader_type);
glShaderSource(shader_id, 1, &shader_code_ptr, NULL);
glCompileShader(shader_id);
check_error(filename, shader_id, GL_COMPILE_STATUS);
// check compile error
return shader_id;
}
Shader::Shader(const std::string& vertexPath, const std::string& fragmentPath) {
unsigned int vertex = load_shader(vertexPath, GL_VERTEX_SHADER);
unsigned int fragment = load_shader(fragmentPath, GL_FRAGMENT_SHADER);
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
check_error("link", ID, GL_LINK_STATUS);
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use() const {
glUseProgram(ID);
}
void Shader::cleanup() {
glDeleteProgram(ID);
}
void Shader::setBool(const std::string &name, bool value) const {
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform1i(uniform, (int)value);
}
void Shader::setInt(const std::string &name, int value) const {
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform1i(uniform, value);
}
void Shader::setFloat(const std::string &name, float value) const {
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform1f(uniform, value);
}
void Shader::setVec4(const std::string &name, float v1, float v2, float v3, float v4) const {
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform4f(uniform, v1, v2, v3, v4);
}
void Shader::setVec4(const std::string &name, const glm::vec4& value) const
{
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform4fv(uniform, 1, &value[0]);
}
void Shader::setVec3(const std::string &name, const glm::vec3& value) const
{
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform3fv(uniform, 1, &value[0]);
}
void Shader::setVec3(const std::string &name, float v1, float v2, float v3) const {
auto uniform = glGetUniformLocation(ID, name.c_str());
glUniform3f(uniform, v1, v2, v3);
}
void Shader::setMat4(const std::string &name, const glm::mat4& mat) const {
unsigned int loc = glGetUniformLocation(ID, name.c_str());
glUniformMatrix4fv(loc, 1, GL_FALSE, glm::value_ptr(mat));
}
void Shader::apply_material(const Material& material) {
setVec3("material.ambient", material.ambient);
setFloat("material.shininess", material.shininess);
}
void Shader::apply_lighting(const Lighting& lighting) {
setInt("pointLightCount", lighting.positioned.size());
setInt("dirLightCount", lighting.directional.size());
for(size_t i = 0; i < lighting.directional.size(); i++) {
apply_dir_light(lighting.directional[i], i);
}
for(size_t i = 0; i < lighting.positioned.size(); i++) {
apply_point_light(lighting.positioned[i], i);
}
// set the first spotlight to the camera light if given
size_t i = 0;
// camera is optional, so only add if used
if(lighting.camera.on) {
apply_spot_light(lighting.camera, 0);
i++;
}
// gross but that's fine for now
for(; i < lighting.spot.size(); i++) {
// need to be off by one because the camera is a spot light
if(lighting.spot[i].on) {
apply_spot_light(lighting.spot[i], i+1);
}
}
// need +1 for the camera spot light
setInt("spotLightCount", (int)i);
}
void Shader::apply_dir_light(const Light& light, size_t index) {
dbc::check(index < MAX_LIGHTS, "too many directional lights");
// nasty, this needs to go
setVec3(std::format("dirLights[{}].direction", index), light.direction);
setVec3(std::format("dirLights[{}].ambient", index), light.ambient);
setVec3(std::format("dirLights[{}].diffuse", index), light.diffuse);
setVec3(std::format("dirLights[{}].specular", index), light.specular);
}
void Shader::apply_point_light(const Light& light, size_t index) {
dbc::check(index < MAX_LIGHTS, "too many positioned lights");
// disgusting, crafting a string on every render?
setVec3(std::format("pointLights[{}].position", index), light.position);
setVec3(std::format("pointLights[{}].ambient", index), light.ambient);
setVec3(std::format("pointLights[{}].diffuse", index), light.diffuse);
setVec3(std::format("pointLights[{}].specular", index), light.specular);
setFloat(std::format("pointLights[{}].constant", index), light.constant);
setFloat(std::format("pointLights[{}].linear", index), light.linear);
setFloat(std::format("pointLights[{}].quadratic", index), light.quadratic);
}
void Shader::apply_spot_light(const Light& light, size_t index) {
dbc::check(index < MAX_LIGHTS, "too many spot lights");
// find a way to not make strings all the time
setVec3(std::format("spotLights[{}].position", index), light.position);
setVec3(std::format("spotLights[{}].direction", index), light.direction);
setVec3(std::format("spotLights[{}].ambient", index), light.ambient);
setVec3(std::format("spotLights[{}].diffuse", index), light.diffuse);
setVec3(std::format("spotLights[{}].specular", index), light.specular);
setFloat(std::format("spotLights[{}].constant", index), light.constant);
setFloat(std::format("spotLights[{}].linear", index), light.linear);
setFloat(std::format("spotLights[{}].quadratic", index), light.quadratic);
setFloat(std::format("spotLights[{}].cut_off", index), glm::cos(glm::radians(light.cut_off)));
setFloat(std::format("spotLights[{}].outer_cut_off", index), glm::cos(glm::radians(light.outer_cut_off)));
}

View file

@ -0,0 +1,37 @@
#pragma once
#include <glad/glad.h>
#include <string>
#include <climits>
#include <glm/glm.hpp>
#include <vector>
#include <format>
#include "dbc.hpp"
#include "components.hpp"
using components::Material, components::Lighting, components::Light;
class Shader
{
public:
unsigned int ID = UINT_MAX;
Shader(const std::string& vertexPath, const std::string& fragmentPath);
unsigned int load_shader(const std::string& filename, GLenum shader_type);
void use() const;
void setBool(const std::string &name, bool value) const;
void setInt(const std::string &name, int value) const;
void setFloat(const std::string &name, float value) const;
void setVec4(const std::string &name, float v1, float v2, float v3, float v4) const;
void setVec4(const std::string &name, const glm::vec4& value) const;
void setVec3(const std::string &name, float v1, float v2, float v3) const;
void setVec3(const std::string &name, const glm::vec3& value) const;
void setMat4(const std::string &name, const glm::mat4& what) const;
void cleanup();
void apply_material(const Material& material);
void apply_lighting(const Lighting& lighting);
void apply_dir_light(const Light& light, size_t index);
void apply_point_light(const Light& light, size_t index);
void apply_spot_light(const Light& light, size_t index);
};

Some files were not shown because too many files have changed in this diff Show more