do skonczenia
363
.gitignore
vendored
Normal file
@ -0,0 +1,363 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
##
|
||||||
|
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.rsuser
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Mono auto generated files
|
||||||
|
mono_crash.*
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
[Ww][Ii][Nn]32/
|
||||||
|
[Aa][Rr][Mm]/
|
||||||
|
[Aa][Rr][Mm]64/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Oo]ut/
|
||||||
|
[Ll]og/
|
||||||
|
[Ll]ogs/
|
||||||
|
|
||||||
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# Visual Studio 2017 auto generated files
|
||||||
|
Generated\ Files/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUnit
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
nunit-*.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# Benchmark Results
|
||||||
|
BenchmarkDotNet.Artifacts/
|
||||||
|
|
||||||
|
# .NET Core
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
# ASP.NET Scaffolding
|
||||||
|
ScaffoldingReadMe.txt
|
||||||
|
|
||||||
|
# StyleCop
|
||||||
|
StyleCopReport.xml
|
||||||
|
|
||||||
|
# Files built by Visual Studio
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_h.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.iobj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.ipdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*_wpftmp.csproj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# Visual Studio Trace Files
|
||||||
|
*.e2e
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# AxoCover is a Code Coverage Tool
|
||||||
|
.axoCover/*
|
||||||
|
!.axoCover/settings.json
|
||||||
|
|
||||||
|
# Coverlet is a free, cross platform Code Coverage Tool
|
||||||
|
coverage*.json
|
||||||
|
coverage*.xml
|
||||||
|
coverage*.info
|
||||||
|
|
||||||
|
# Visual Studio code coverage results
|
||||||
|
*.coverage
|
||||||
|
*.coveragexml
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# NuGet Symbol Packages
|
||||||
|
*.snupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/[Pp]ackages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/[Pp]ackages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/[Pp]ackages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignorable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
*.appx
|
||||||
|
*.appxbundle
|
||||||
|
*.appxupload
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!?*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Including strong name files can present a security risk
|
||||||
|
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||||
|
#*.snk
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
ServiceFabricBackup/
|
||||||
|
*.rptproj.bak
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
*.ndf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
*.rptproj.rsuser
|
||||||
|
*- [Bb]ackup.rdl
|
||||||
|
*- [Bb]ackup ([0-9]).rdl
|
||||||
|
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||||
|
*.vbw
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# CodeRush personal settings
|
||||||
|
.cr/personal
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Cake - Uncomment if you are using it
|
||||||
|
# tools/**
|
||||||
|
# !tools/packages.config
|
||||||
|
|
||||||
|
# Tabs Studio
|
||||||
|
*.tss
|
||||||
|
|
||||||
|
# Telerik's JustMock configuration file
|
||||||
|
*.jmconfig
|
||||||
|
|
||||||
|
# BizTalk build output
|
||||||
|
*.btp.cs
|
||||||
|
*.btm.cs
|
||||||
|
*.odx.cs
|
||||||
|
*.xsd.cs
|
||||||
|
|
||||||
|
# OpenCover UI analysis results
|
||||||
|
OpenCover/
|
||||||
|
|
||||||
|
# Azure Stream Analytics local run output
|
||||||
|
ASALocalRun/
|
||||||
|
|
||||||
|
# MSBuild Binary and Structured Log
|
||||||
|
*.binlog
|
||||||
|
|
||||||
|
# NVidia Nsight GPU debugger configuration file
|
||||||
|
*.nvuser
|
||||||
|
|
||||||
|
# MFractors (Xamarin productivity tool) working folder
|
||||||
|
.mfractor/
|
||||||
|
|
||||||
|
# Local History for Visual Studio
|
||||||
|
.localhistory/
|
||||||
|
|
||||||
|
# BeatPulse healthcheck temp database
|
||||||
|
healthchecksdb
|
||||||
|
|
||||||
|
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||||
|
MigrationBackup/
|
||||||
|
|
||||||
|
# Ionide (cross platform F# VS Code tools) working folder
|
||||||
|
.ionide/
|
||||||
|
|
||||||
|
# Fody - auto-generated XML schema
|
||||||
|
FodyWeavers.xsd
|
BIN
assimp-vc141-mt.dll
Normal file
BIN
assimp-vc141-mtd.dll
Normal file
BIN
cw 11/assimp-vc141-mt.dll
Normal file
BIN
cw 11/assimp-vc141-mtd.dll
Normal file
BIN
cw 11/freeglut.dll
Normal file
BIN
cw 11/glew32.dll
Normal file
126
cw 11/grk-cw10.vcxproj
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Box.cpp" />
|
||||||
|
<ClCompile Include="src\Camera.cpp" />
|
||||||
|
<ClCompile Include="src\main.cpp" />
|
||||||
|
<ClCompile Include="src\Render_Utils.cpp" />
|
||||||
|
<ClCompile Include="src\Shader_Loader.cpp" />
|
||||||
|
<ClCompile Include="src\SOIL\image_DXT.c" />
|
||||||
|
<ClCompile Include="src\SOIL\image_helper.c" />
|
||||||
|
<ClCompile Include="src\SOIL\SOIL.c" />
|
||||||
|
<ClCompile Include="src\SOIL\stb_image_aug.c" />
|
||||||
|
<ClCompile Include="src\Texture.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\Camera.h" />
|
||||||
|
<ClInclude Include="src\ex_10_1.hpp" />
|
||||||
|
<ClInclude Include="src\objload.h" />
|
||||||
|
<ClInclude Include="src\Render_Utils.h" />
|
||||||
|
<ClInclude Include="src\Shader_Loader.h" />
|
||||||
|
<ClInclude Include="src\SOIL\image_DXT.h" />
|
||||||
|
<ClInclude Include="src\SOIL\image_helper.h" />
|
||||||
|
<ClInclude Include="src\SOIL\SOIL.h" />
|
||||||
|
<ClInclude Include="src\SOIL\stbi_DDS_aug.h" />
|
||||||
|
<ClInclude Include="src\SOIL\stbi_DDS_aug_c.h" />
|
||||||
|
<ClInclude Include="src\SOIL\stb_image_aug.h" />
|
||||||
|
<ClInclude Include="src\Texture.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="shaders\shader_9_1.frag" />
|
||||||
|
<None Include="shaders\shader_9_1.vert" />
|
||||||
|
<None Include="shaders\shader_8_sun.frag" />
|
||||||
|
<None Include="shaders\shader_8_sun.vert" />
|
||||||
|
<None Include="shaders\test.frag" />
|
||||||
|
<None Include="shaders\test.vert" />
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<ProjectGuid>{8DF85446-560F-459F-BB86-0477FCA30165}</ProjectGuid>
|
||||||
|
<Keyword>Win32Proj</Keyword>
|
||||||
|
<RootNamespace>grk-cw10</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||||
|
<ProjectName>grk-cw10</ProjectName>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<PlatformToolset>v143</PlatformToolset>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<LibraryPath>$(SolutionDir)dependencies\freeglut\lib;$(SolutionDir)dependencies\glew-2.0.0\lib\Release\Win32;$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019;$(SolutionDir)dependencies\assimp;$(LibraryPath)</LibraryPath>
|
||||||
|
<IncludePath>$(SolutionDir)dependencies\freeglut\include\GL;$(SolutionDir)dependencies\glew-2.0.0\include\GL;$(SolutionDir)dependencies\glm;$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\include;$(SolutionDir)dependencies\assimp\include;$(IncludePath)</IncludePath>
|
||||||
|
<ExecutablePath>$(ExecutablePath)</ExecutablePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
<LibraryPath>$(SolutionDir)dependencies\freeglut\lib;$(SolutionDir)dependencies\glew-2.0.0\lib\Release\Win32;$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019;$(SolutionDir)dependencies\assimp;$(LibraryPath)</LibraryPath>
|
||||||
|
<IncludePath>$(SolutionDir)dependencies\freeglut\include\GL;$(SolutionDir)dependencies\glew-2.0.0\include\GL;$(SolutionDir)dependencies\glm;$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\include;$(SolutionDir)dependencies\assimp\include;$(IncludePath)</IncludePath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<AdditionalDependencies>opengl32.lib;freeglut.lib;glew32.lib;$(SolutionDir)\dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019\glfw3.lib;$(SolutionDir)\dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019\glfw3dll.lib;zlibd.lib;assimp-vc141-mtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<PrecompiledHeader>
|
||||||
|
</PrecompiledHeader>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
<AdditionalDependencies>opengl32.lib;freeglut.lib;glew32.lib;$(SolutionDir)\dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019\glfw3.lib;$(SolutionDir)\dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019\glfw3dll.lib;zlibd.lib;assimp-vc141-mtd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
|
<AdditionalLibraryDirectories>$(SolutionDir)dependencies\glfw-3.3.8.bin.WIN32\lib-vc2019;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
113
cw 11/grk-cw10.vcxproj.filters
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Shader Files">
|
||||||
|
<UniqueIdentifier>{0a247bb8-2e8e-4a90-b0ef-17415b0941ba}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Source Files\SOIL">
|
||||||
|
<UniqueIdentifier>{0af44075-33f4-4953-b1d6-1d28d61d758f}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="src\Render_Utils.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Shader_Loader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Box.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Camera.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\Texture.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SOIL\SOIL.c">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SOIL\stb_image_aug.c">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SOIL\image_DXT.c">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="src\SOIL\image_helper.c">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="src\objload.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Render_Utils.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Shader_Loader.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Camera.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\Texture.h">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\image_helper.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\SOIL.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\stb_image_aug.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\stbi_DDS_aug.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\stbi_DDS_aug_c.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\SOIL\image_DXT.h">
|
||||||
|
<Filter>Source Files\SOIL</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="src\ex_10_1.hpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="shaders\shader_8_sun.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_8_sun.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_9_1.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\shader_9_1.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\test.frag">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
<None Include="shaders\test.vert">
|
||||||
|
<Filter>Shader Files</Filter>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
BIN
cw 11/img/2.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
cw 11/img/3.webp
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
cw 11/img/384px-PerlinNoiseDotProducts.png
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
cw 11/img/384px-PerlinNoiseInterpolated.png
Normal file
After Width: | Height: | Size: 54 KiB |
BIN
cw 11/img/4.png
Normal file
After Width: | Height: | Size: 7.0 KiB |
BIN
cw 11/img/5.webp
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
cw 11/img/6.webp
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
cw 11/img/7.webp
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
cw 11/img/8.webp
Normal file
After Width: | Height: | Size: 34 KiB |
1254
cw 11/img/Figure_1.eps
Normal file
BIN
cw 11/img/PerlinNoiseDotProducts.png
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
cw 11/img/PerlinNoiseGradientGrid.png
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
cw 11/img/PerlinNoiseInterpolated.png
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
cw 11/img/blending1.webp
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
cw 11/img/camera.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
cw 11/img/capture.webm
Normal file
BIN
cw 11/img/coordinate_systems.jpg
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
cw 11/img/cubemaps_sampling.png
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
cw 11/img/gamma_correction_brightness.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
cw 11/img/lighting_result.png
Normal file
After Width: | Height: | Size: 190 KiB |
BIN
cw 11/img/noise_examples.jpg
Normal file
After Width: | Height: | Size: 329 KiB |
BIN
cw 11/img/shadow_mapping_projection.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
cw 11/img/shadows1.bmp
Normal file
After Width: | Height: | Size: 978 KiB |
BIN
cw 11/img/spotlight.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
cw 11/img/stride_offest.jpg
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
cw 11/img/stride_offest_2_2.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
cw 11/img/struktura.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
cw 11/img/sun.png
Normal file
After Width: | Height: | Size: 2.0 MiB |
BIN
cw 11/img/textures.png
Normal file
After Width: | Height: | Size: 260 KiB |
BIN
cw 11/img/z_depth_graph.jpg
Normal file
After Width: | Height: | Size: 80 KiB |
BIN
cw 11/img/z_depth_graph2.jpg
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
cw 11/models/arm.blend
Normal file
BIN
cw 11/models/arm.fbx
Normal file
BIN
cw 11/models/blade-runner-style-cityscapes.fbx
Normal file
BIN
cw 11/models/city_small.fbx
Normal file
BIN
cw 11/models/flying_car.fbx
Normal file
BIN
cw 11/models/flying_car_2.fbx
Normal file
BIN
cw 11/models/flying_car_3.fbx
Normal file
BIN
cw 11/models/path.fbx
Normal file
377
cw 11/particle_generator.cpp
Normal file
@ -0,0 +1,377 @@
|
|||||||
|
#define FOURCC_DXT1 0x31545844 // Equivalent to "DXT1" in ASCII
|
||||||
|
#define FOURCC_DXT3 0x33545844 // Equivalent to "DXT3" in ASCII
|
||||||
|
#define FOURCC_DXT5 0x35545844 // Equivalent to "DXT5" in ASCII
|
||||||
|
#include "glew.h"
|
||||||
|
#include "freeglut.h"
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "../glm/gtx/norm.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
GLuint billboard_vertex_buffer;
|
||||||
|
GLuint particles_position_buffer;
|
||||||
|
GLuint particles_color_buffer;
|
||||||
|
|
||||||
|
GLuint particleTexture;
|
||||||
|
|
||||||
|
static GLfloat* g_particule_position_size_data;
|
||||||
|
static GLubyte* g_particule_color_data;
|
||||||
|
|
||||||
|
struct ParticleSource {
|
||||||
|
glm::vec3 pos;
|
||||||
|
double amount;
|
||||||
|
float spread;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<ParticleSource> particleSources;
|
||||||
|
|
||||||
|
int ParticlesCount = 0;
|
||||||
|
double lastTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
|
||||||
|
|
||||||
|
// CPU representation of a particle
|
||||||
|
struct Particle {
|
||||||
|
glm::vec3 pos, speed;
|
||||||
|
unsigned char r, g, b, a;
|
||||||
|
float size, angle, weight;
|
||||||
|
float life;
|
||||||
|
float cameradistance;
|
||||||
|
|
||||||
|
bool operator<(const Particle& that) const {
|
||||||
|
return this->cameradistance > that.cameradistance;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void addParticleSource(glm::vec3 pos, double amount, float spread) {
|
||||||
|
ParticleSource particleSource;
|
||||||
|
particleSource.pos = pos;
|
||||||
|
particleSource.amount = amount;
|
||||||
|
particleSource.spread = spread;
|
||||||
|
|
||||||
|
particleSources.push_back(particleSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int MaxParticles = 100000;
|
||||||
|
Particle ParticlesContainer[MaxParticles];
|
||||||
|
int LastUsedParticle = 0;
|
||||||
|
|
||||||
|
// Finds a Particle in ParticlesContainer which isn't used yet.
|
||||||
|
// (i.e. life < 0);
|
||||||
|
int FindUnusedParticle() {
|
||||||
|
|
||||||
|
for (int i = LastUsedParticle; i < MaxParticles; i++) {
|
||||||
|
if (ParticlesContainer[i].life < 0) {
|
||||||
|
LastUsedParticle = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < LastUsedParticle; i++) {
|
||||||
|
if (ParticlesContainer[i].life < 0) {
|
||||||
|
LastUsedParticle = i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SortParticles() {
|
||||||
|
std::sort(&ParticlesContainer[0], &ParticlesContainer[MaxParticles]);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint loadDDS(const char* imagepath)
|
||||||
|
{
|
||||||
|
unsigned char header[124];
|
||||||
|
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
/* try to open the file */
|
||||||
|
fp = fopen(imagepath, "rb");
|
||||||
|
if (fp == NULL) {
|
||||||
|
printf("%s could not be opened. Are you in the right directory ? Don't forget to read the FAQ !\n", imagepath); getchar();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify the type of file */
|
||||||
|
char filecode[4];
|
||||||
|
fread(filecode, 1, 4, fp);
|
||||||
|
if (strncmp(filecode, "DDS ", 4) != 0) {
|
||||||
|
fclose(fp);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the surface desc */
|
||||||
|
fread(&header, 124, 1, fp);
|
||||||
|
|
||||||
|
unsigned int height = *(unsigned int*)&(header[8]);
|
||||||
|
unsigned int width = *(unsigned int*)&(header[12]);
|
||||||
|
unsigned int linearSize = *(unsigned int*)&(header[16]);
|
||||||
|
unsigned int mipMapCount = *(unsigned int*)&(header[24]);
|
||||||
|
unsigned int fourCC = *(unsigned int*)&(header[80]);
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char* buffer;
|
||||||
|
unsigned int bufsize;
|
||||||
|
/* how big is it going to be including all mipmaps? */
|
||||||
|
bufsize = mipMapCount > 1 ? linearSize * 2 : linearSize;
|
||||||
|
buffer = (unsigned char*)malloc(bufsize * sizeof(unsigned char));
|
||||||
|
fread(buffer, 1, bufsize, fp);
|
||||||
|
/* close the file pointer */
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
unsigned int components = (fourCC == FOURCC_DXT1) ? 3 : 4;
|
||||||
|
unsigned int format;
|
||||||
|
switch (fourCC)
|
||||||
|
{
|
||||||
|
case FOURCC_DXT1:
|
||||||
|
format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
|
||||||
|
break;
|
||||||
|
case FOURCC_DXT3:
|
||||||
|
format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
|
||||||
|
break;
|
||||||
|
case FOURCC_DXT5:
|
||||||
|
format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create one OpenGL texture
|
||||||
|
GLuint textureID;
|
||||||
|
glGenTextures(1, &textureID);
|
||||||
|
|
||||||
|
// "Bind" the newly created texture : all future texture functions will modify this texture
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
unsigned int blockSize = (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) ? 8 : 16;
|
||||||
|
unsigned int offset = 0;
|
||||||
|
|
||||||
|
/* load the mipmaps */
|
||||||
|
for (unsigned int level = 0; level < mipMapCount && (width || height); ++level)
|
||||||
|
{
|
||||||
|
unsigned int size = ((width + 3) / 4) * ((height + 3) / 4) * blockSize;
|
||||||
|
glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height,
|
||||||
|
0, size, buffer + offset);
|
||||||
|
|
||||||
|
offset += size;
|
||||||
|
width /= 2;
|
||||||
|
height /= 2;
|
||||||
|
|
||||||
|
// Deal with Non-Power-Of-Two textures. This code is not included in the webpage to reduce clutter.
|
||||||
|
if (width < 1) width = 1;
|
||||||
|
if (height < 1) height = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
return textureID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initParticles() {
|
||||||
|
particleTexture = loadDDS("textures/particle.dds");
|
||||||
|
|
||||||
|
g_particule_position_size_data = new GLfloat[MaxParticles * 4];
|
||||||
|
g_particule_color_data = new GLubyte[MaxParticles * 4];
|
||||||
|
|
||||||
|
for (int i = 0; i < MaxParticles; i++) {
|
||||||
|
ParticlesContainer[i].life = -1.0f;
|
||||||
|
ParticlesContainer[i].cameradistance = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The VBO containing the 4 vertices of the particles.
|
||||||
|
// Thanks to instancing, they will be shared by all particles.
|
||||||
|
static const GLfloat g_vertex_buffer_data[] = {
|
||||||
|
-0.5f, -0.5f, 0.0f,
|
||||||
|
0.5f, -0.5f, 0.0f,
|
||||||
|
-0.5f, 0.5f, 0.0f,
|
||||||
|
0.5f, 0.5f, 0.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenBuffers(1, &billboard_vertex_buffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
// The VBO containing the positions and sizes of the particles
|
||||||
|
glGenBuffers(1, &particles_position_buffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
||||||
|
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
|
||||||
|
|
||||||
|
// The VBO containing the colors of the particles
|
||||||
|
glGenBuffers(1, &particles_color_buffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
||||||
|
// Initialize with empty (NULL) buffer : it will be updated later, each frame.
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void spawnParticles(double deltaTime, glm::vec3 sourcePosition, double amount, float spread) {
|
||||||
|
|
||||||
|
int newparticles = (int)(deltaTime * amount);
|
||||||
|
if (newparticles > (int)(0.016f * amount))
|
||||||
|
newparticles = (int)(0.016f * amount);
|
||||||
|
|
||||||
|
for (int i = 0; i < newparticles; i++) {
|
||||||
|
int particleIndex = FindUnusedParticle();
|
||||||
|
ParticlesContainer[particleIndex].life = 20.0f;
|
||||||
|
|
||||||
|
ParticlesContainer[particleIndex].pos = sourcePosition;
|
||||||
|
|
||||||
|
glm::vec3 maindir = glm::vec3(0.0f, 0.4f, 0.0f);
|
||||||
|
|
||||||
|
glm::vec3 randomdir = glm::vec3(
|
||||||
|
(rand() % 2000 - 1000.0f) / 1000.0f,
|
||||||
|
(rand() % 2000 - 1000.0f) / 1000.0f,
|
||||||
|
(rand() % 2000 - 1000.0f) / 1000.0f
|
||||||
|
);
|
||||||
|
|
||||||
|
ParticlesContainer[particleIndex].speed = maindir + randomdir * spread;
|
||||||
|
|
||||||
|
ParticlesContainer[particleIndex].r = 200;
|
||||||
|
ParticlesContainer[particleIndex].g = 200;
|
||||||
|
ParticlesContainer[particleIndex].b = 255;
|
||||||
|
ParticlesContainer[particleIndex].a = (rand() % 32) / 3 + 100;
|
||||||
|
|
||||||
|
ParticlesContainer[particleIndex].size = (rand() % 1000) / 100000.0f + 0.05f;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void simulateParticles(glm::vec3 cameraPos, double deltaTime) {
|
||||||
|
ParticlesCount = 0;
|
||||||
|
for (int i = 0; i < MaxParticles; i++) {
|
||||||
|
|
||||||
|
Particle& p = ParticlesContainer[i];
|
||||||
|
|
||||||
|
if (p.life > 0.0f) {
|
||||||
|
|
||||||
|
// Decrease life
|
||||||
|
p.life -= deltaTime;
|
||||||
|
if (p.life > 0.0f) {
|
||||||
|
|
||||||
|
// Simulate simple physics : gravity only, no collisions
|
||||||
|
// decreased acceleration - bubbles were too fast
|
||||||
|
p.speed += glm::vec3(0.0f, 1.0f, 0.0f) * (float)deltaTime * 0.5f;
|
||||||
|
p.pos += p.speed * (float)deltaTime;
|
||||||
|
p.cameradistance = glm::length2(p.pos - cameraPos);
|
||||||
|
|
||||||
|
// Fill the GPU buffer
|
||||||
|
g_particule_position_size_data[4 * ParticlesCount + 0] = p.pos.x;
|
||||||
|
g_particule_position_size_data[4 * ParticlesCount + 1] = p.pos.y;
|
||||||
|
g_particule_position_size_data[4 * ParticlesCount + 2] = p.pos.z;
|
||||||
|
|
||||||
|
g_particule_position_size_data[4 * ParticlesCount + 3] = p.size;
|
||||||
|
|
||||||
|
g_particule_color_data[4 * ParticlesCount + 0] = p.r;
|
||||||
|
g_particule_color_data[4 * ParticlesCount + 1] = p.g;
|
||||||
|
g_particule_color_data[4 * ParticlesCount + 2] = p.b;
|
||||||
|
g_particule_color_data[4 * ParticlesCount + 3] = p.a;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p.cameradistance = -1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticlesCount++;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SortParticles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateParticles() {
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_data);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bindParticles(GLuint programParticles, glm::vec3 cameraSide, glm::vec3 cameraVertical, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix) {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
|
||||||
|
glUseProgram(programParticles);
|
||||||
|
|
||||||
|
// Vertex shader
|
||||||
|
GLuint CameraRight_worldspace_ID = glGetUniformLocation(programParticles, "CameraRight_worldspace");
|
||||||
|
GLuint CameraUp_worldspace_ID = glGetUniformLocation(programParticles, "CameraUp_worldspace");
|
||||||
|
GLuint ViewProjMatrixID = glGetUniformLocation(programParticles, "VP");
|
||||||
|
|
||||||
|
// fragment shader
|
||||||
|
GLuint TextureID = glGetUniformLocation(programParticles, "myTextureSampler");
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, particleTexture);
|
||||||
|
|
||||||
|
glUniform1i(TextureID, 0);
|
||||||
|
|
||||||
|
glUniform3f(CameraRight_worldspace_ID, cameraSide.x, cameraSide.y, cameraSide.z);
|
||||||
|
glUniform3f(CameraUp_worldspace_ID, cameraVertical.x, cameraVertical.y, cameraVertical.z);
|
||||||
|
|
||||||
|
glm::mat4 transformation = perspectiveMatrix * cameraMatrix;
|
||||||
|
glUniformMatrix4fv(ViewProjMatrixID, 1, GL_FALSE, (float*)&transformation);
|
||||||
|
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, billboard_vertex_buffer);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||||
|
|
||||||
|
// positions of particles' centers
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
|
||||||
|
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
||||||
|
|
||||||
|
// particles' colors
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
|
||||||
|
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, (void*)0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderParticles() {
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
||||||
|
glVertexAttribDivisor(0, 0); // particles vertices : always reuse the same 4 vertices -> 0
|
||||||
|
glVertexAttribDivisor(1, 1); // positions : one per quad (its center) -> 1
|
||||||
|
glVertexAttribDivisor(2, 1); // color : one per quad -> 1
|
||||||
|
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(0);
|
||||||
|
glDisableVertexAttribArray(1);
|
||||||
|
glDisableVertexAttribArray(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleAllParticleSources(glm::vec3 cameraPos, GLuint programParticles, glm::vec3 cameraSide, glm::vec3 cameraVertical, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix) {
|
||||||
|
double currentTime = glutGet(GLUT_ELAPSED_TIME) / 1000.0f;
|
||||||
|
double delta = currentTime - lastTime;
|
||||||
|
lastTime = currentTime;
|
||||||
|
for (ParticleSource particleSource : particleSources)
|
||||||
|
{
|
||||||
|
spawnParticles(delta, particleSource.pos, particleSource.amount, particleSource.spread);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((int)currentTime % 1 == 0) {
|
||||||
|
particleSources.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
simulateParticles(cameraPos, delta);
|
||||||
|
updateParticles();
|
||||||
|
bindParticles(programParticles, cameraSide, cameraVertical, cameraMatrix, perspectiveMatrix);
|
||||||
|
renderParticles();
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdownParticles() {
|
||||||
|
delete[] g_particule_position_size_data;
|
||||||
|
glDeleteBuffers(1, &particles_color_buffer);
|
||||||
|
glDeleteBuffers(1, &particles_position_buffer);
|
||||||
|
glDeleteBuffers(1, &billboard_vertex_buffer);
|
||||||
|
}
|
7
cw 11/particle_generator.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "freeglut.h"
|
||||||
|
void initParticles();
|
||||||
|
void handleAllParticleSources(glm::vec3 cameraPos, GLuint programParticles, glm::vec3 cameraSide, glm::vec3 cameraVertical, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix);
|
||||||
|
void shutdownParticles();
|
||||||
|
void addParticleSource(glm::vec3 pos, double amount, float spread);
|
7
cw 11/render.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
import os
|
||||||
|
rootdir = './'
|
||||||
|
for filename in os.listdir(rootdir):
|
||||||
|
if filename.endswith(".md"):
|
||||||
|
name = filename[:-3]
|
||||||
|
os.system(f'pandoc -s -o "{name}.html" "{name}.md" --mathjax --css style.css')
|
21
cw 11/shaders/shader_4_1.frag
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
uniform vec3 objectColor;
|
||||||
|
//uniform vec3 lightDir;
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
in vec3 fragPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(lightPos-fragPos);
|
||||||
|
vec3 V = normalize(cameraPos-fragPos);
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
vec3 R = reflect(-normalize(lightDir),normal);
|
||||||
|
|
||||||
|
float specular = pow(max(0,dot(R,V)),10);
|
||||||
|
float diffuse = max(0,dot(normal,normalize(lightDir)));
|
||||||
|
gl_FragColor = vec4(mix(objectColor,objectColor*diffuse+vec3(1)*specular,0.9), 1.0);
|
||||||
|
}
|
17
cw 11/shaders/shader_4_1.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec2 vertexTexCoord;
|
||||||
|
layout(location = 2) in vec3 vertexNormal;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
out vec3 interpNormal;
|
||||||
|
out vec3 fragPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix*vec4(vertexNormal,0)).xyz;
|
||||||
|
fragPos = (modelMatrix*vec4(vertexPosition,1)).xyz;
|
||||||
|
}
|
17
cw 11/shaders/shader_4_sun.frag
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
uniform vec3 objectColor;
|
||||||
|
//uniform vec3 lightDir;
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
in vec3 fragPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
vec3 V = normalize(cameraPos-fragPos);
|
||||||
|
float coef = max(0,dot(V,normal));
|
||||||
|
gl_FragColor = vec4(mix(objectColor,vec3(1,0.5,0.1),1-coef), 1.0);
|
||||||
|
}
|
17
cw 11/shaders/shader_4_sun.vert
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec2 vertexTexCoord;
|
||||||
|
layout(location = 2) in vec3 vertexNormal;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
out vec3 interpNormal;
|
||||||
|
out vec3 fragPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix*vec4(vertexNormal,0)).xyz;
|
||||||
|
fragPos = (modelMatrix*vec4(vertexPosition,1)).xyz;
|
||||||
|
}
|
18
cw 11/shaders/shader_5_1_tex.frag
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
float AMBIENT = 0.1;
|
||||||
|
|
||||||
|
uniform vec3 color;
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
|
||||||
|
in vec3 vecNormal;
|
||||||
|
in vec3 worldPos;
|
||||||
|
|
||||||
|
out vec4 outColor;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 lightDir = normalize(lightPos-worldPos);
|
||||||
|
vec3 normal = normalize(vecNormal);
|
||||||
|
float diffuse=max(0,dot(normal,lightDir));
|
||||||
|
outColor = vec4(color*min(1,AMBIENT+diffuse), 1.0);
|
||||||
|
}
|
18
cw 11/shaders/shader_5_1_tex.vert
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
|
||||||
|
out vec3 vecNormal;
|
||||||
|
out vec3 worldPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz;
|
||||||
|
vecNormal = (modelMatrix* vec4(vertexNormal,0)).xyz;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
}
|
11
cw 11/shaders/shader_8_sun.frag
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
uniform vec3 color;
|
||||||
|
uniform float exposition;
|
||||||
|
|
||||||
|
|
||||||
|
out vec4 outColor;
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
outColor = vec4(vec3(1.0) - exp(-color*exposition),1);
|
||||||
|
}
|
13
cw 11/shaders/shader_8_sun.vert
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
//gl_Position = vec4(vertexPosition, 1.0);
|
||||||
|
}
|
135
cw 11/shaders/shader_9_1.frag
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
float AMBIENT = 0.03;
|
||||||
|
float PI = 3.14;
|
||||||
|
|
||||||
|
uniform sampler2D depthMap;
|
||||||
|
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
|
||||||
|
uniform vec3 color;
|
||||||
|
|
||||||
|
uniform vec3 sunDir;
|
||||||
|
uniform vec3 sunColor;
|
||||||
|
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 lightColor;
|
||||||
|
|
||||||
|
uniform vec3 spotlightPos;
|
||||||
|
uniform vec3 spotlightColor;
|
||||||
|
uniform vec3 spotlightConeDir;
|
||||||
|
uniform vec3 spotlightPhi;
|
||||||
|
|
||||||
|
uniform float metallic;
|
||||||
|
uniform float roughness;
|
||||||
|
|
||||||
|
uniform float exposition;
|
||||||
|
|
||||||
|
in vec3 vecNormal;
|
||||||
|
in vec3 worldPos;
|
||||||
|
|
||||||
|
out vec4 outColor;
|
||||||
|
|
||||||
|
|
||||||
|
in vec3 viewDirTS;
|
||||||
|
in vec3 lightDirTS;
|
||||||
|
in vec3 spotlightDirTS;
|
||||||
|
in vec3 sunDirTS;
|
||||||
|
|
||||||
|
in vec3 test;
|
||||||
|
|
||||||
|
float DistributionGGX(vec3 normal, vec3 H, float roughness){
|
||||||
|
float a = roughness*roughness;
|
||||||
|
float a2 = a*a;
|
||||||
|
float NdotH = max(dot(normal, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float num = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness){
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float num = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return num / denom;
|
||||||
|
}
|
||||||
|
float GeometrySmith(vec3 normal, vec3 V, vec3 lightDir, float roughness){
|
||||||
|
float NdotV = max(dot(normal, V), 0.0);
|
||||||
|
float NdotL = max(dot(normal, lightDir), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0){
|
||||||
|
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 PBRLight(vec3 lightDir, vec3 radiance, vec3 normal, vec3 V){
|
||||||
|
float diffuse=max(0,dot(normal,lightDir));
|
||||||
|
|
||||||
|
//vec3 V = normalize(cameraPos-worldPos);
|
||||||
|
vec3 F0 = vec3(0.04);
|
||||||
|
F0 = mix(F0, color, metallic);
|
||||||
|
|
||||||
|
vec3 H = normalize(V + lightDir);
|
||||||
|
|
||||||
|
// cook-torrance brdf
|
||||||
|
float NDF = DistributionGGX(normal, H, roughness);
|
||||||
|
float G = GeometrySmith(normal, V, lightDir, roughness);
|
||||||
|
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||||
|
|
||||||
|
vec3 kS = F;
|
||||||
|
vec3 kD = vec3(1.0) - kS;
|
||||||
|
kD *= 1.0 - metallic;
|
||||||
|
|
||||||
|
vec3 numerator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * max(dot(normal, V), 0.0) * max(dot(normal, lightDir), 0.0) + 0.0001;
|
||||||
|
vec3 specular = numerator / denominator;
|
||||||
|
|
||||||
|
// add to outgoing radiance Lo
|
||||||
|
float NdotL = max(dot(normal, lightDir), 0.0);
|
||||||
|
return (kD * color / PI + specular) * radiance * NdotL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//vec3 normal = vec3(0,0,1);
|
||||||
|
vec3 normal = normalize(vecNormal);
|
||||||
|
|
||||||
|
//vec3 viewDir = normalize(viewDirTS);
|
||||||
|
vec3 viewDir = normalize(cameraPos-worldPos);
|
||||||
|
|
||||||
|
//vec3 lightDir = normalize(lightDirTS);
|
||||||
|
vec3 lightDir = normalize(lightPos-worldPos);
|
||||||
|
|
||||||
|
|
||||||
|
vec3 ambient = AMBIENT*color;
|
||||||
|
vec3 attenuatedlightColor = lightColor/pow(length(lightPos-worldPos),2);
|
||||||
|
vec3 ilumination;
|
||||||
|
ilumination = ambient+PBRLight(lightDir,attenuatedlightColor,normal,viewDir);
|
||||||
|
|
||||||
|
//flashlight
|
||||||
|
//vec3 spotlightDir= normalize(spotlightDirTS);
|
||||||
|
vec3 spotlightDir= normalize(spotlightPos-worldPos);
|
||||||
|
|
||||||
|
|
||||||
|
float angle_atenuation = clamp((dot(-normalize(spotlightPos-worldPos),spotlightConeDir)-0.5)*3,0,1);
|
||||||
|
attenuatedlightColor = angle_atenuation*spotlightColor/pow(length(spotlightPos-worldPos),2);
|
||||||
|
ilumination=ilumination+PBRLight(spotlightDir,attenuatedlightColor,normal,viewDir);
|
||||||
|
|
||||||
|
//sun
|
||||||
|
ilumination=ilumination+PBRLight(sunDir,sunColor,normal,viewDir);
|
||||||
|
|
||||||
|
|
||||||
|
outColor = vec4(vec3(1.0) - exp(-ilumination*exposition),1);
|
||||||
|
//outColor = vec4(roughness,metallic,0,1);
|
||||||
|
//outColor = vec4(test;
|
||||||
|
}
|
43
cw 11/shaders/shader_9_1.vert
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
layout(location = 3) in vec3 vertexTangent;
|
||||||
|
layout(location = 4) in vec3 vertexBitangent;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
|
||||||
|
out vec3 vecNormal;
|
||||||
|
out vec3 worldPos;
|
||||||
|
|
||||||
|
uniform vec3 lightPos;
|
||||||
|
uniform vec3 spotlightPos;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec3 sunDir;
|
||||||
|
|
||||||
|
out vec3 viewDirTS;
|
||||||
|
out vec3 lightDirTS;
|
||||||
|
out vec3 spotlightDirTS;
|
||||||
|
out vec3 sunDirTS;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
worldPos = (modelMatrix* vec4(vertexPosition,1)).xyz;
|
||||||
|
vecNormal = (modelMatrix* vec4(vertexNormal,0)).xyz;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
|
||||||
|
vec3 w_tangent = normalize(mat3(modelMatrix)*vertexTangent);
|
||||||
|
vec3 w_bitangent = normalize(mat3(modelMatrix)*vertexBitangent);
|
||||||
|
mat3 TBN = transpose(mat3(w_tangent, w_bitangent, vecNormal));
|
||||||
|
|
||||||
|
vec3 V = normalize(cameraPos-worldPos);
|
||||||
|
viewDirTS = TBN*V;
|
||||||
|
vec3 L = normalize(lightPos-worldPos);
|
||||||
|
lightDirTS = TBN*L;
|
||||||
|
vec3 SL = normalize(spotlightPos-worldPos);
|
||||||
|
spotlightDirTS = TBN*SL;
|
||||||
|
sunDirTS = TBN*sunDir;
|
||||||
|
|
||||||
|
}
|
14
cw 11/shaders/shader_color.frag
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
uniform vec3 objectColor;
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
float ambient = 0.2;
|
||||||
|
float diffuse = max(dot(normal, -lightDir), 0.0);
|
||||||
|
gl_FragColor = vec4(objectColor * (ambient + (1-ambient) * diffuse), 1.0);
|
||||||
|
}
|
16
cw 11/shaders/shader_color.vert
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec2 vertexTexCoord;
|
||||||
|
layout(location = 2) in vec3 vertexNormal;
|
||||||
|
|
||||||
|
uniform mat4 modelViewProjectionMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
|
||||||
|
out vec3 interpNormal;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = modelViewProjectionMatrix * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix * vec4(vertexNormal, 0.0)).xyz;
|
||||||
|
}
|
6
cw 11/shaders/shader_red.frag
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_FragColor = vec4(1.0,0.0,0.0, 1.0);
|
||||||
|
}
|
10
cw 11/shaders/shader_red.vert
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
uniform mat4 modelViewProjectionMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = modelViewProjectionMatrix * vec4(vertexPosition, 1.0);
|
||||||
|
}
|
29
cw 11/shaders/shader_spec_tex.frag
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
//uniform vec3 objectColor;
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
//uniform vec3 lightPos;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform sampler2D color_texture;
|
||||||
|
uniform sampler2D specular_texture;
|
||||||
|
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
in vec3 fragPos;
|
||||||
|
in vec2 uvCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//float falloff = pow(length(cameraPos-fragPos),2)*0.01;
|
||||||
|
vec3 color = texture(color_texture,uvCoord).rgb;
|
||||||
|
vec3 spec = texture(specular_texture,uvCoord).rgb;
|
||||||
|
//vec3 lightDir = normalize(lightPos-fragPos);
|
||||||
|
vec3 V = normalize(cameraPos-fragPos);
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
vec3 R = reflect(-normalize(lightDir),normal);
|
||||||
|
|
||||||
|
float specular = pow(max(0,dot(R,V)),10);
|
||||||
|
float diffuse = max(0,dot(normal,normalize(lightDir)));
|
||||||
|
gl_FragColor = vec4(mix(color,color*diffuse+spec*specular,0.7), 1.0);
|
||||||
|
//gl_FragColor = vec4(mix(vec3(0.1,0.1,0.1),mix(color,color*diffuse+spec*specular,0.7),min(1,1/falloff)), 1.0);
|
||||||
|
}
|
19
cw 11/shaders/shader_spec_tex.vert
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
out vec3 interpNormal;
|
||||||
|
out vec3 fragPos;
|
||||||
|
out vec2 uvCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvCoord = vertexTexCoord;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix*vec4(vertexNormal,0)).xyz;
|
||||||
|
fragPos = (modelMatrix*vec4(vertexPosition,1)).xyz;
|
||||||
|
}
|
17
cw 11/shaders/shader_tex.frag
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
uniform sampler2D textureSampler;
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
in vec2 interpTexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vec2 modifiedTexCoord = vec2(interpTexCoord.x, 1.0 - interpTexCoord.y); // Poprawka dla tekstur Ziemi, ktore bez tego wyswietlaja sie 'do gory nogami'
|
||||||
|
vec3 color = texture2D(textureSampler, modifiedTexCoord).rgb;
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
float ambient = 0.2;
|
||||||
|
float diffuse = max(dot(normal, -lightDir), 0.0);
|
||||||
|
gl_FragColor = vec4(color * (ambient + (1-ambient) * diffuse), 1.0);
|
||||||
|
}
|
18
cw 11/shaders/shader_tex.vert
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec2 vertexTexCoord;
|
||||||
|
layout(location = 2) in vec3 vertexNormal;
|
||||||
|
|
||||||
|
uniform mat4 modelViewProjectionMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
|
||||||
|
out vec3 interpNormal;
|
||||||
|
out vec2 interpTexCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = modelViewProjectionMatrix * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix * vec4(vertexNormal, 0.0)).xyz;
|
||||||
|
interpTexCoord = vertexTexCoord;
|
||||||
|
}
|
28
cw 11/shaders/shader_tex_2.frag
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
//uniform vec3 objectColor;
|
||||||
|
uniform vec3 lightDir;
|
||||||
|
//uniform vec3 lightPos;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform sampler2D color_texture;
|
||||||
|
|
||||||
|
|
||||||
|
in vec3 interpNormal;
|
||||||
|
in vec3 fragPos;
|
||||||
|
in vec2 uvCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
//float falloff = pow(length(cameraPos-fragPos),2)*0.01;
|
||||||
|
vec3 color = texture(color_texture,uvCoord).rgb;
|
||||||
|
vec3 spec = vec3(0.7);
|
||||||
|
//vec3 lightDir = normalize(lightPos-fragPos);
|
||||||
|
vec3 V = normalize(cameraPos-fragPos);
|
||||||
|
vec3 normal = normalize(interpNormal);
|
||||||
|
vec3 R = reflect(-normalize(lightDir),normal);
|
||||||
|
|
||||||
|
float specular = pow(max(0,dot(R,V)),10);
|
||||||
|
float diffuse = max(0,dot(normal,normalize(lightDir)));
|
||||||
|
gl_FragColor = vec4(mix(color,color*diffuse+spec*specular,0.7), 1.0);
|
||||||
|
//gl_FragColor = vec4(mix(vec3(0.1,0.1,0.1),mix(color,color*diffuse+spec*specular,0.7),min(1,1/falloff)), 1.0);
|
||||||
|
}
|
19
cw 11/shaders/shader_tex_2.vert
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
uniform mat4 transformation;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
out vec3 interpNormal;
|
||||||
|
out vec3 fragPos;
|
||||||
|
out vec2 uvCoord;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
uvCoord = vertexTexCoord;
|
||||||
|
gl_Position = transformation * vec4(vertexPosition, 1.0);
|
||||||
|
interpNormal = (modelMatrix*vec4(vertexNormal,0)).xyz;
|
||||||
|
fragPos = (modelMatrix*vec4(vertexPosition,1)).xyz;
|
||||||
|
}
|
12
cw 11/shaders/test.frag
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
in vec2 tc;
|
||||||
|
|
||||||
|
uniform sampler2D depthMap;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
float depthValue = texture(depthMap, tc).r;
|
||||||
|
FragColor = vec4(vec3(depthValue+0.5), 1.0);
|
||||||
|
}
|
14
cw 11/shaders/test.vert
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#version 410 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 vertexPosition;
|
||||||
|
layout(location = 1) in vec3 vertexNormal;
|
||||||
|
layout(location = 2) in vec2 vertexTexCoord;
|
||||||
|
|
||||||
|
|
||||||
|
out vec2 tc;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
tc = vertexTexCoord;
|
||||||
|
gl_Position = vec4(vertexPosition*0.9, 1.0);
|
||||||
|
}
|
55
cw 11/src/Box.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
|
||||||
|
|
||||||
|
// dane 36 wierzcholkow i kolorow opisujace model pudelka
|
||||||
|
const float box[] = {
|
||||||
|
|
||||||
|
// points colors
|
||||||
|
0.25f, 0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, 0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
-0.25f, 0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
-0.25f, 0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
-0.25f, -0.25f, -0.75f, 1.0f, 0.8f, 0.8f, 0.8f, 1.0f,
|
||||||
|
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, 0.25f, 0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, 0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, 0.25f, 0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
0.25f, 0.25f, -0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.5f, 0.5f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, 0.25f, -0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
0.25f, 0.25f, 0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, 0.25f, -0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, 0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
-0.25f, 0.25f, -0.75f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
|
||||||
|
0.25f, -0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, -0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, 0.75f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
31
cw 11/src/Camera.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include "Camera.h"
|
||||||
|
|
||||||
|
glm::mat4 Core::createPerspectiveMatrix(float zNear, float zFar, float frustumScale)
|
||||||
|
{
|
||||||
|
glm::mat4 perspective;
|
||||||
|
perspective[0][0] = 1.f;
|
||||||
|
perspective[1][1] = frustumScale;
|
||||||
|
perspective[2][2] = (zFar + zNear) / (zNear - zFar);
|
||||||
|
perspective[3][2] = (2 * zFar * zNear) / (zNear - zFar);
|
||||||
|
perspective[2][3] = -1;
|
||||||
|
perspective[3][3] = 0;
|
||||||
|
|
||||||
|
return perspective;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 Core::createViewMatrix( glm::vec3 position, glm::vec3 forward, glm::vec3 up )
|
||||||
|
{
|
||||||
|
glm::vec3 side = glm::cross(forward, up);
|
||||||
|
|
||||||
|
// Trzeba pamietac o minusie przy ustawianiu osi Z kamery.
|
||||||
|
// Wynika to z tego, ze standardowa macierz perspektywiczna zaklada, ze "z przodu" jest ujemna (a nie dodatnia) czesc osi Z.
|
||||||
|
glm::mat4 cameraRotation;
|
||||||
|
cameraRotation[0][0] = side.x; cameraRotation[1][0] = side.y; cameraRotation[2][0] = side.z;
|
||||||
|
cameraRotation[0][1] = up.x; cameraRotation[1][1] = up.y; cameraRotation[2][1] = up.z;
|
||||||
|
cameraRotation[0][2] = -forward.x; cameraRotation[1][2] = -forward.y; cameraRotation[2][2] = -forward.z;
|
||||||
|
|
||||||
|
glm::mat4 cameraTranslation;
|
||||||
|
cameraTranslation[3] = glm::vec4(-position, 1.0f);
|
||||||
|
|
||||||
|
return cameraRotation * cameraTranslation;
|
||||||
|
}
|
14
cw 11/src/Camera.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glm.hpp"
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
glm::mat4 createPerspectiveMatrix(float zNear = 0.1f, float zFar = 100.0f, float frustumScale = 1.f);
|
||||||
|
|
||||||
|
// position - pozycja kamery
|
||||||
|
// forward - wektor "do przodu" kamery (jednostkowy)
|
||||||
|
// up - wektor "w gore" kamery (jednostkowy)
|
||||||
|
// up i forward musza byc ortogonalne!
|
||||||
|
glm::mat4 createViewMatrix(glm::vec3 position, glm::vec3 forward, glm::vec3 up);
|
||||||
|
}
|
240
cw 11/src/Render_Utils.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
#include "Render_Utils.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "glew.h"
|
||||||
|
#include "freeglut.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Core::RenderContext::initFromOBJ(obj::Model& model)
|
||||||
|
{
|
||||||
|
vertexArray = 0;
|
||||||
|
vertexBuffer = 0;
|
||||||
|
vertexIndexBuffer = 0;
|
||||||
|
unsigned int vertexDataBufferSize = sizeof(float) * model.vertex.size();
|
||||||
|
unsigned int vertexNormalBufferSize = sizeof(float) * model.normal.size();
|
||||||
|
unsigned int vertexTexBufferSize = sizeof(float) * model.texCoord.size();
|
||||||
|
|
||||||
|
size = model.faces["default"].size();
|
||||||
|
unsigned int vertexElementBufferSize = sizeof(unsigned int) * size;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<unsigned int> indices;
|
||||||
|
for (unsigned short index : model.faces["default"]) {
|
||||||
|
indices.push_back(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vertexArray);
|
||||||
|
glBindVertexArray(vertexArray);
|
||||||
|
|
||||||
|
|
||||||
|
glGenBuffers(1, &vertexIndexBuffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexElementBufferSize, &indices[0], GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glGenBuffers(1, &vertexBuffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize, NULL, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexDataBufferSize, &model.vertex[0]);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize, vertexNormalBufferSize, &model.normal[0]);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize, vertexTexBufferSize, &model.texCoord[0]);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
||||||
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)(vertexDataBufferSize));
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)(vertexNormalBufferSize + vertexDataBufferSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::RenderContext::initFromAssimpMesh(aiMesh* mesh){
|
||||||
|
vertexArray = 0;
|
||||||
|
vertexBuffer = 0;
|
||||||
|
vertexIndexBuffer = 0;
|
||||||
|
|
||||||
|
std::vector<float> textureCoord;
|
||||||
|
std::vector<unsigned int> indices;
|
||||||
|
//tex coord must be converted to 2d vecs
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||||
|
{
|
||||||
|
if (mesh->mTextureCoords[0]!=nullptr) {
|
||||||
|
textureCoord.push_back(mesh->mTextureCoords[0][i].x);
|
||||||
|
textureCoord.push_back(mesh->mTextureCoords[0][i].y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
textureCoord.push_back(0.0f);
|
||||||
|
textureCoord.push_back(0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mesh->mTextureCoords[0] == nullptr) {
|
||||||
|
std::cout << "no uv coords\n";
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i < mesh->mNumFaces; i++)
|
||||||
|
{
|
||||||
|
aiFace face = mesh->mFaces[i];
|
||||||
|
// retrieve all indices of the face and store them in the indices vector
|
||||||
|
for (unsigned int j = 0; j < face.mNumIndices; j++)
|
||||||
|
indices.push_back(face.mIndices[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int vertexDataBufferSize = sizeof(float) * mesh->mNumVertices * 3;
|
||||||
|
unsigned int vertexNormalBufferSize = sizeof(float) * mesh->mNumVertices * 3;
|
||||||
|
unsigned int vertexTexBufferSize = sizeof(float) * mesh->mNumVertices * 2;
|
||||||
|
unsigned int vertexTangentBufferSize = sizeof(float) * mesh->mNumVertices * 3;
|
||||||
|
unsigned int vertexBiTangentBufferSize = sizeof(float) * mesh->mNumVertices * 3;
|
||||||
|
|
||||||
|
unsigned int vertexElementBufferSize = sizeof(unsigned int) * indices.size();
|
||||||
|
size = indices.size();
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vertexArray);
|
||||||
|
glBindVertexArray(vertexArray);
|
||||||
|
|
||||||
|
|
||||||
|
glGenBuffers(1, &vertexIndexBuffer);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, vertexElementBufferSize, &indices[0], GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glGenBuffers(1, &vertexBuffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
|
||||||
|
//std::cout << vertexBuffer;
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glEnableVertexAttribArray(4);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize + vertexTangentBufferSize + vertexBiTangentBufferSize, NULL, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vertexDataBufferSize, mesh->mVertices);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize, vertexNormalBufferSize, mesh->mNormals);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize, vertexTexBufferSize, &textureCoord[0]);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize, vertexTangentBufferSize, mesh->mTangents);
|
||||||
|
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize + vertexTangentBufferSize, vertexBiTangentBufferSize, mesh->mBitangents);
|
||||||
|
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)(vertexDataBufferSize));
|
||||||
|
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)(vertexNormalBufferSize + vertexDataBufferSize));
|
||||||
|
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 0, (void*)(vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize));
|
||||||
|
glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, 0, (void*)(vertexDataBufferSize + vertexNormalBufferSize + vertexTexBufferSize + vertexTangentBufferSize));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::RenderContext::render()
|
||||||
|
{
|
||||||
|
|
||||||
|
glBindVertexArray(this->vertexArray);
|
||||||
|
glDrawElements(
|
||||||
|
GL_TRIANGLES, // mode
|
||||||
|
this->size, // count
|
||||||
|
GL_UNSIGNED_INT, // type
|
||||||
|
(void*)0 // element array buffer offset
|
||||||
|
);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Core::DrawVertexArray(const float * vertexArray, int numVertices, int elementSize )
|
||||||
|
{
|
||||||
|
glVertexAttribPointer(0, elementSize, GL_FLOAT, false, 0, vertexArray);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, numVertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::DrawVertexArrayIndexed( const float * vertexArray, const int * indexArray, int numIndexes, int elementSize )
|
||||||
|
{
|
||||||
|
glVertexAttribPointer(0, elementSize, GL_FLOAT, false, 0, vertexArray);
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glDrawElements(GL_TRIANGLES, numIndexes, GL_UNSIGNED_INT, indexArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Core::DrawVertexArray( const VertexData & data )
|
||||||
|
{
|
||||||
|
int numAttribs = std::min(VertexData::MAX_ATTRIBS, data.NumActiveAttribs);
|
||||||
|
for(int i = 0; i < numAttribs; i++)
|
||||||
|
{
|
||||||
|
glVertexAttribPointer(i, data.Attribs[i].Size, GL_FLOAT, false, 0, data.Attribs[i].Pointer);
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, data.NumVertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::DiffuseMaterial::init_data() {
|
||||||
|
glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z);
|
||||||
|
Core::SetActiveTexture(texture, "color_texture", program, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::DiffuseSpecularMaterial::init_data() {
|
||||||
|
glUniform3f(glGetUniformLocation(program, "lightDir"), lightDir.x, lightDir.y, lightDir.z);
|
||||||
|
Core::SetActiveTexture(texture, "color_texture", program, 0);
|
||||||
|
Core::SetActiveTexture(textureSpecular, "specular_texture", program, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Core::RayContext::render()
|
||||||
|
{
|
||||||
|
|
||||||
|
glBindVertexArray(vertexArray);
|
||||||
|
glDrawArrays(
|
||||||
|
GL_LINES,// mode
|
||||||
|
0, //start
|
||||||
|
3 * 7 * 2 // count
|
||||||
|
);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Core::initRay(RayContext& rayContext) {
|
||||||
|
rayContext.size = 2;
|
||||||
|
glGenVertexArrays(1, &rayContext.vertexArray);
|
||||||
|
glBindVertexArray(rayContext.vertexArray);
|
||||||
|
|
||||||
|
glGenBuffers(1, &rayContext.vertexBuffer);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, rayContext.vertexBuffer);
|
||||||
|
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 3 * 7 * 2 * sizeof(float), NULL, GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)(0));
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
void Core::updateRayPos(RayContext& rayContext,std::vector<glm::vec3> ray) {
|
||||||
|
glBindVertexArray(rayContext.vertexArray);
|
||||||
|
std::vector<glm::vec3> keyPoints;
|
||||||
|
float offset = 4.f;
|
||||||
|
float scale = 0.2f;
|
||||||
|
float rayEnd = 50.f;
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset);
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * rayEnd);
|
||||||
|
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset + scale * glm::vec3(1.f, 1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset - scale * glm::vec3(1.f, 1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset + scale * glm::vec3(1.f, -1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset - scale * glm::vec3(1.f, -1.f, 0.f));
|
||||||
|
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset + scale * glm::vec3(1.f, 1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * rayEnd * scale);
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset - scale * glm::vec3(1.f, 1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * rayEnd * scale);
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset + scale * glm::vec3(1.f, -1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * rayEnd * scale);
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * offset - scale * glm::vec3(1.f, -1.f, 0.f));
|
||||||
|
keyPoints.push_back(ray[0] + ray[1] * rayEnd * scale);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, rayContext.vertexBuffer);
|
||||||
|
glBufferSubData(GL_ARRAY_BUFFER, 0, keyPoints.size()*3 * sizeof(float), &keyPoints[0]);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
118
cw 11/src/Render_Utils.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "ext.hpp"
|
||||||
|
#include "glew.h"
|
||||||
|
#include "objload.h"
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
#define BUFFER_OFFSET(i) ((char *)NULL + (i))
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
static inline glm::mat4 mat4_cast(const aiMatrix4x4& m) { return glm::transpose(glm::make_mat4(&m.a1)); }
|
||||||
|
|
||||||
|
struct Material {
|
||||||
|
GLuint program;
|
||||||
|
virtual void init_data() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DiffuseMaterial : Core::Material {
|
||||||
|
GLuint texture;
|
||||||
|
glm::vec3 lightDir;
|
||||||
|
void init_data();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DiffuseSpecularMaterial : Core::Material {
|
||||||
|
GLuint texture;
|
||||||
|
GLuint textureSpecular;
|
||||||
|
glm::vec3 lightDir;
|
||||||
|
void init_data();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RenderContext
|
||||||
|
{
|
||||||
|
|
||||||
|
GLuint vertexArray;
|
||||||
|
GLuint vertexBuffer;
|
||||||
|
GLuint vertexIndexBuffer;
|
||||||
|
Material* material;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
void initFromOBJ(obj::Model& model);
|
||||||
|
|
||||||
|
void initFromAssimpMesh(aiMesh* mesh);
|
||||||
|
|
||||||
|
void render();
|
||||||
|
};
|
||||||
|
struct RayContext : RenderContext {
|
||||||
|
|
||||||
|
void render();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
std::vector<RenderContext> renderContexts;
|
||||||
|
glm::mat4 matrix;
|
||||||
|
int parent;
|
||||||
|
std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
// vertexArray - jednowymiarowa tablica zawierajaca wartosci opisujace pozycje kolejnych wierzcholkow w jednym ciagu (x1, y1, z1, w1, x2, y2, z2, w2, ...)
|
||||||
|
// numVertices - liczba wierzcholkow do narysowania
|
||||||
|
// elementSize - liczba wartosci opisujacych pojedynczy wierzcholek (np. 3 gdy wierzcholek opisany jest trojka (x, y, z))
|
||||||
|
void DrawVertexArray(const float * vertexArray, int numVertices, int elementSize);
|
||||||
|
|
||||||
|
// indexArray - jednowymiarowa tablica zawierajaca indeksy wierzcholkow kolejnych trojkatow w jednym ciagu (t1_i1, t1_i2, t1_i3, t2_i1, t2_i2, t2_i3, ...)
|
||||||
|
// numIndexes - liczba indeksow w tablicy indexArray
|
||||||
|
void DrawVertexArrayIndexed(const float * vertexArray, const int * indexArray, int numIndexes, int elementSize);
|
||||||
|
|
||||||
|
|
||||||
|
struct VertexAttribute
|
||||||
|
{
|
||||||
|
const void * Pointer;
|
||||||
|
int Size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VertexData
|
||||||
|
{
|
||||||
|
static const int MAX_ATTRIBS = 8;
|
||||||
|
VertexAttribute Attribs[MAX_ATTRIBS];
|
||||||
|
int NumActiveAttribs;
|
||||||
|
int NumVertices;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ta funkcja sluzy do rysowania trojkatow, ktorych wierzcholki moga byc opisane wiecej niz jednym atrybutem.
|
||||||
|
// Funkcja przyjmuje jako parametr strukture, w ktorej nalezy zawrzec wszystkie potrzebne dane.
|
||||||
|
//
|
||||||
|
// Przykladowe wywolanie funkcji - narysowanie trojkata jak na pierwszych zajeciach:
|
||||||
|
/*
|
||||||
|
|
||||||
|
const float vertices[] = {
|
||||||
|
0.25f, 0.25f, 0.0f, 1.0f,
|
||||||
|
0.25f, -0.25f, 0.0f, 1.0f,
|
||||||
|
-0.25f, -0.25f, 0.0f, 1.0f
|
||||||
|
};
|
||||||
|
|
||||||
|
Core::VertexData vertexData;
|
||||||
|
vertexData.NumActiveAttribs = 1; // Liczba uzywanych atrybutow wierzcholka
|
||||||
|
vertexData.Attribs[0].Pointer = vertices; // Wskaznik na dane zerowego atrybutu
|
||||||
|
vertexData.Attribs[0].Size = 4; // Wielkosc zerowego atrybutu (ilosc liczb opisujacych ten atrybut w pojedynczym wierzcholku)
|
||||||
|
vertexData.NumVertices = 3; // Liczba wierzcholkow do narysowania
|
||||||
|
Core::DrawVertexArray(vertexData);
|
||||||
|
|
||||||
|
*/
|
||||||
|
void DrawVertexArray(const VertexData & data);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void initRay(RayContext& rayContext);
|
||||||
|
|
||||||
|
void updateRayPos(RayContext& rayContext, std::vector<glm::vec3> keyPoints);
|
||||||
|
|
||||||
|
//void DrawContext(Core::RayContext& rayContext);
|
||||||
|
|
||||||
|
}
|
2024
cw 11/src/SOIL/SOIL.c
Normal file
433
cw 11/src/SOIL/SOIL.h
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
/**
|
||||||
|
@mainpage SOIL
|
||||||
|
|
||||||
|
Jonathan Dummer
|
||||||
|
2007-07-26-10.36
|
||||||
|
|
||||||
|
Simple OpenGL Image Library
|
||||||
|
|
||||||
|
A tiny c library for uploading images as
|
||||||
|
textures into OpenGL. Also saving and
|
||||||
|
loading of images is supported.
|
||||||
|
|
||||||
|
I'm using Sean's Tool Box image loader as a base:
|
||||||
|
http://www.nothings.org/
|
||||||
|
|
||||||
|
I'm upgrading it to load TGA and DDS files, and a direct
|
||||||
|
path for loading DDS files straight into OpenGL textures,
|
||||||
|
when applicable.
|
||||||
|
|
||||||
|
Image Formats:
|
||||||
|
- BMP load & save
|
||||||
|
- TGA load & save
|
||||||
|
- DDS load & save
|
||||||
|
- PNG load
|
||||||
|
- JPG load
|
||||||
|
|
||||||
|
OpenGL Texture Features:
|
||||||
|
- resample to power-of-two sizes
|
||||||
|
- MIPmap generation
|
||||||
|
- compressed texture S3TC formats (if supported)
|
||||||
|
- can pre-multiply alpha for you, for better compositing
|
||||||
|
- can flip image about the y-axis (except pre-compressed DDS files)
|
||||||
|
|
||||||
|
Thanks to:
|
||||||
|
* Sean Barret - for the awesome stb_image
|
||||||
|
* Dan Venkitachalam - for finding some non-compliant DDS files, and patching some explicit casts
|
||||||
|
* everybody at gamedev.net
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY
|
||||||
|
#define HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
The format of images that may be loaded (force_channels).
|
||||||
|
SOIL_LOAD_AUTO leaves the image in whatever format it was found.
|
||||||
|
SOIL_LOAD_L forces the image to load as Luminous (greyscale)
|
||||||
|
SOIL_LOAD_LA forces the image to load as Luminous with Alpha
|
||||||
|
SOIL_LOAD_RGB forces the image to load as Red Green Blue
|
||||||
|
SOIL_LOAD_RGBA forces the image to load as Red Green Blue Alpha
|
||||||
|
**/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SOIL_LOAD_AUTO = 0,
|
||||||
|
SOIL_LOAD_L = 1,
|
||||||
|
SOIL_LOAD_LA = 2,
|
||||||
|
SOIL_LOAD_RGB = 3,
|
||||||
|
SOIL_LOAD_RGBA = 4
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Passed in as reuse_texture_ID, will cause SOIL to
|
||||||
|
register a new texture ID using glGenTextures().
|
||||||
|
If the value passed into reuse_texture_ID > 0 then
|
||||||
|
SOIL will just re-use that texture ID (great for
|
||||||
|
reloading image assets in-game!)
|
||||||
|
**/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SOIL_CREATE_NEW_ID = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
flags you can pass into SOIL_load_OGL_texture()
|
||||||
|
and SOIL_create_OGL_texture().
|
||||||
|
(note that if SOIL_FLAG_DDS_LOAD_DIRECT is used
|
||||||
|
the rest of the flags with the exception of
|
||||||
|
SOIL_FLAG_TEXTURE_REPEATS will be ignored while
|
||||||
|
loading already-compressed DDS files.)
|
||||||
|
|
||||||
|
SOIL_FLAG_POWER_OF_TWO: force the image to be POT
|
||||||
|
SOIL_FLAG_MIPMAPS: generate mipmaps for the texture
|
||||||
|
SOIL_FLAG_TEXTURE_REPEATS: otherwise will clamp
|
||||||
|
SOIL_FLAG_MULTIPLY_ALPHA: for using (GL_ONE,GL_ONE_MINUS_SRC_ALPHA) blending
|
||||||
|
SOIL_FLAG_INVERT_Y: flip the image vertically
|
||||||
|
SOIL_FLAG_COMPRESS_TO_DXT: if the card can display them, will convert RGB to DXT1, RGBA to DXT5
|
||||||
|
SOIL_FLAG_DDS_LOAD_DIRECT: will load DDS files directly without _ANY_ additional processing
|
||||||
|
SOIL_FLAG_NTSC_SAFE_RGB: clamps RGB components to the range [16,235]
|
||||||
|
SOIL_FLAG_CoCg_Y: Google YCoCg; RGB=>CoYCg, RGBA=>CoCgAY
|
||||||
|
SOIL_FLAG_TEXTURE_RECTANGE: uses ARB_texture_rectangle ; pixel indexed & no repeat or MIPmaps or cubemaps
|
||||||
|
**/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SOIL_FLAG_POWER_OF_TWO = 1,
|
||||||
|
SOIL_FLAG_MIPMAPS = 2,
|
||||||
|
SOIL_FLAG_TEXTURE_REPEATS = 4,
|
||||||
|
SOIL_FLAG_MULTIPLY_ALPHA = 8,
|
||||||
|
SOIL_FLAG_INVERT_Y = 16,
|
||||||
|
SOIL_FLAG_COMPRESS_TO_DXT = 32,
|
||||||
|
SOIL_FLAG_DDS_LOAD_DIRECT = 64,
|
||||||
|
SOIL_FLAG_NTSC_SAFE_RGB = 128,
|
||||||
|
SOIL_FLAG_CoCg_Y = 256,
|
||||||
|
SOIL_FLAG_TEXTURE_RECTANGLE = 512
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
The types of images that may be saved.
|
||||||
|
(TGA supports uncompressed RGB / RGBA)
|
||||||
|
(BMP supports uncompressed RGB)
|
||||||
|
(DDS supports DXT1 and DXT5)
|
||||||
|
**/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SOIL_SAVE_TYPE_TGA = 0,
|
||||||
|
SOIL_SAVE_TYPE_BMP = 1,
|
||||||
|
SOIL_SAVE_TYPE_DDS = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Defines the order of faces in a DDS cubemap.
|
||||||
|
I recommend that you use the same order in single
|
||||||
|
image cubemap files, so they will be interchangeable
|
||||||
|
with DDS cubemaps when using SOIL.
|
||||||
|
**/
|
||||||
|
#define SOIL_DDS_CUBEMAP_FACE_ORDER "EWUDNS"
|
||||||
|
|
||||||
|
/**
|
||||||
|
The types of internal fake HDR representations
|
||||||
|
|
||||||
|
SOIL_HDR_RGBE: RGB * pow( 2.0, A - 128.0 )
|
||||||
|
SOIL_HDR_RGBdivA: RGB / A
|
||||||
|
SOIL_HDR_RGBdivA2: RGB / (A*A)
|
||||||
|
**/
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SOIL_HDR_RGBE = 0,
|
||||||
|
SOIL_HDR_RGBdivA = 1,
|
||||||
|
SOIL_HDR_RGBdivA2 = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads an image from disk into an OpenGL texture.
|
||||||
|
\param filename the name of the file to upload as a texture
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_texture
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads 6 images from disk into an OpenGL cubemap texture.
|
||||||
|
\param x_pos_file the name of the file to upload as the +x cube face
|
||||||
|
\param x_neg_file the name of the file to upload as the -x cube face
|
||||||
|
\param y_pos_file the name of the file to upload as the +y cube face
|
||||||
|
\param y_neg_file the name of the file to upload as the -y cube face
|
||||||
|
\param z_pos_file the name of the file to upload as the +z cube face
|
||||||
|
\param z_neg_file the name of the file to upload as the -z cube face
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_cubemap
|
||||||
|
(
|
||||||
|
const char *x_pos_file,
|
||||||
|
const char *x_neg_file,
|
||||||
|
const char *y_pos_file,
|
||||||
|
const char *y_neg_file,
|
||||||
|
const char *z_pos_file,
|
||||||
|
const char *z_neg_file,
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads 1 image from disk and splits it into an OpenGL cubemap texture.
|
||||||
|
\param filename the name of the file to upload as a texture
|
||||||
|
\param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc.
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_single_cubemap
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
const char face_order[6],
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads an HDR image from disk into an OpenGL texture.
|
||||||
|
\param filename the name of the file to upload as a texture
|
||||||
|
\param fake_HDR_format SOIL_HDR_RGBE, SOIL_HDR_RGBdivA, SOIL_HDR_RGBdivA2
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_HDR_texture
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int fake_HDR_format,
|
||||||
|
int rescale_to_max,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads an image from RAM into an OpenGL texture.
|
||||||
|
\param buffer the image data in RAM just as if it were still in a file
|
||||||
|
\param buffer_length the size of the buffer in bytes
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_texture_from_memory
|
||||||
|
(
|
||||||
|
const unsigned char *const buffer,
|
||||||
|
int buffer_length,
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads 6 images from memory into an OpenGL cubemap texture.
|
||||||
|
\param x_pos_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param x_pos_buffer_length the size of the above buffer
|
||||||
|
\param x_neg_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param x_neg_buffer_length the size of the above buffer
|
||||||
|
\param y_pos_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param y_pos_buffer_length the size of the above buffer
|
||||||
|
\param y_neg_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param y_neg_buffer_length the size of the above buffer
|
||||||
|
\param z_pos_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param z_pos_buffer_length the size of the above buffer
|
||||||
|
\param z_neg_buffer the image data in RAM to upload as the +x cube face
|
||||||
|
\param z_neg_buffer_length the size of the above buffer
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_cubemap_from_memory
|
||||||
|
(
|
||||||
|
const unsigned char *const x_pos_buffer,
|
||||||
|
int x_pos_buffer_length,
|
||||||
|
const unsigned char *const x_neg_buffer,
|
||||||
|
int x_neg_buffer_length,
|
||||||
|
const unsigned char *const y_pos_buffer,
|
||||||
|
int y_pos_buffer_length,
|
||||||
|
const unsigned char *const y_neg_buffer,
|
||||||
|
int y_neg_buffer_length,
|
||||||
|
const unsigned char *const z_pos_buffer,
|
||||||
|
int z_pos_buffer_length,
|
||||||
|
const unsigned char *const z_neg_buffer,
|
||||||
|
int z_neg_buffer_length,
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads 1 image from RAM and splits it into an OpenGL cubemap texture.
|
||||||
|
\param buffer the image data in RAM just as if it were still in a file
|
||||||
|
\param buffer_length the size of the buffer in bytes
|
||||||
|
\param face_order the order of the faces in the file, any combination of NSWEUD, for North, South, Up, etc.
|
||||||
|
\param force_channels 0-image format, 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_load_OGL_single_cubemap_from_memory
|
||||||
|
(
|
||||||
|
const unsigned char *const buffer,
|
||||||
|
int buffer_length,
|
||||||
|
const char face_order[6],
|
||||||
|
int force_channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates a 2D OpenGL texture from raw image data. Note that the raw data is
|
||||||
|
_NOT_ freed after the upload (so the user can load various versions).
|
||||||
|
\param data the raw data to be uploaded as an OpenGL texture
|
||||||
|
\param width the width of the image in pixels
|
||||||
|
\param height the height of the image in pixels
|
||||||
|
\param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_create_OGL_texture
|
||||||
|
(
|
||||||
|
const unsigned char *const data,
|
||||||
|
int width, int height, int channels,
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Creates an OpenGL cubemap texture by splitting up 1 image into 6 parts.
|
||||||
|
\param data the raw data to be uploaded as an OpenGL texture
|
||||||
|
\param width the width of the image in pixels
|
||||||
|
\param height the height of the image in pixels
|
||||||
|
\param channels the number of channels: 1-luminous, 2-luminous/alpha, 3-RGB, 4-RGBA
|
||||||
|
\param face_order the order of the faces in the file, and combination of NSWEUD, for North, South, Up, etc.
|
||||||
|
\param reuse_texture_ID 0-generate a new texture ID, otherwise reuse the texture ID (overwriting the old texture)
|
||||||
|
\param flags can be any of SOIL_FLAG_POWER_OF_TWO | SOIL_FLAG_MIPMAPS | SOIL_FLAG_TEXTURE_REPEATS | SOIL_FLAG_MULTIPLY_ALPHA | SOIL_FLAG_INVERT_Y | SOIL_FLAG_COMPRESS_TO_DXT | SOIL_FLAG_DDS_LOAD_DIRECT
|
||||||
|
\return 0-failed, otherwise returns the OpenGL texture handle
|
||||||
|
**/
|
||||||
|
unsigned int
|
||||||
|
SOIL_create_OGL_single_cubemap
|
||||||
|
(
|
||||||
|
const unsigned char *const data,
|
||||||
|
int width, int height, int channels,
|
||||||
|
const char face_order[6],
|
||||||
|
unsigned int reuse_texture_ID,
|
||||||
|
unsigned int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Captures the OpenGL window (RGB) and saves it to disk
|
||||||
|
\return 0 if it failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
SOIL_save_screenshot
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int image_type,
|
||||||
|
int x, int y,
|
||||||
|
int width, int height
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads an image from disk into an array of unsigned chars.
|
||||||
|
Note that *channels return the original channel count of the
|
||||||
|
image. If force_channels was other than SOIL_LOAD_AUTO,
|
||||||
|
the resulting image has force_channels, but *channels may be
|
||||||
|
different (if the original image had a different channel
|
||||||
|
count).
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
unsigned char*
|
||||||
|
SOIL_load_image
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int *width, int *height, int *channels,
|
||||||
|
int force_channels
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Loads an image from memory into an array of unsigned chars.
|
||||||
|
Note that *channels return the original channel count of the
|
||||||
|
image. If force_channels was other than SOIL_LOAD_AUTO,
|
||||||
|
the resulting image has force_channels, but *channels may be
|
||||||
|
different (if the original image had a different channel
|
||||||
|
count).
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
unsigned char*
|
||||||
|
SOIL_load_image_from_memory
|
||||||
|
(
|
||||||
|
const unsigned char *const buffer,
|
||||||
|
int buffer_length,
|
||||||
|
int *width, int *height, int *channels,
|
||||||
|
int force_channels
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Saves an image from an array of unsigned chars (RGBA) to disk
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
SOIL_save_image
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int image_type,
|
||||||
|
int width, int height, int channels,
|
||||||
|
const unsigned char *const data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Frees the image data (note, this is just C's "free()"...this function is
|
||||||
|
present mostly so C++ programmers don't forget to use "free()" and call
|
||||||
|
"delete []" instead [8^)
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
SOIL_free_image_data
|
||||||
|
(
|
||||||
|
unsigned char *img_data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function resturn a pointer to a string describing the last thing
|
||||||
|
that happened inside SOIL. It can be used to determine why an image
|
||||||
|
failed to load.
|
||||||
|
**/
|
||||||
|
const char*
|
||||||
|
SOIL_last_result
|
||||||
|
(
|
||||||
|
void
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HEADER_SIMPLE_OPENGL_IMAGE_LIBRARY */
|
632
cw 11/src/SOIL/image_DXT.c
Normal file
@ -0,0 +1,632 @@
|
|||||||
|
/*
|
||||||
|
Jonathan Dummer
|
||||||
|
2007-07-31-10.32
|
||||||
|
|
||||||
|
simple DXT compression / decompression code
|
||||||
|
|
||||||
|
public domain
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "image_DXT.h"
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
/* set this =1 if you want to use the covarince matrix method...
|
||||||
|
which is better than my method of using standard deviations
|
||||||
|
overall, except on the infintesimal chance that the power
|
||||||
|
method fails for finding the largest eigenvector */
|
||||||
|
#define USE_COV_MAT 1
|
||||||
|
|
||||||
|
/********* Function Prototypes *********/
|
||||||
|
/*
|
||||||
|
Takes a 4x4 block of pixels and compresses it into 8 bytes
|
||||||
|
in DXT1 format (color only, no alpha). Speed is valued
|
||||||
|
over prettyness, at least for now.
|
||||||
|
*/
|
||||||
|
void compress_DDS_color_block(
|
||||||
|
int channels,
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
unsigned char compressed[8] );
|
||||||
|
/*
|
||||||
|
Takes a 4x4 block of pixels and compresses the alpha
|
||||||
|
component it into 8 bytes for use in DXT5 DDS files.
|
||||||
|
Speed is valued over prettyness, at least for now.
|
||||||
|
*/
|
||||||
|
void compress_DDS_alpha_block(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
unsigned char compressed[8] );
|
||||||
|
|
||||||
|
/********* Actual Exposed Functions *********/
|
||||||
|
int
|
||||||
|
save_image_as_DDS
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int width, int height, int channels,
|
||||||
|
const unsigned char *const data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* variables */
|
||||||
|
FILE *fout;
|
||||||
|
unsigned char *DDS_data;
|
||||||
|
DDS_header header;
|
||||||
|
int DDS_size;
|
||||||
|
/* error check */
|
||||||
|
if( (NULL == filename) ||
|
||||||
|
(width < 1) || (height < 1) ||
|
||||||
|
(channels < 1) || (channels > 4) ||
|
||||||
|
(data == NULL ) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* Convert the image */
|
||||||
|
if( (channels & 1) == 1 )
|
||||||
|
{
|
||||||
|
/* no alpha, just use DXT1 */
|
||||||
|
DDS_data = convert_image_to_DXT1( data, width, height, channels, &DDS_size );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* has alpha, so use DXT5 */
|
||||||
|
DDS_data = convert_image_to_DXT5( data, width, height, channels, &DDS_size );
|
||||||
|
}
|
||||||
|
/* save it */
|
||||||
|
memset( &header, 0, sizeof( DDS_header ) );
|
||||||
|
header.dwMagic = ('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24);
|
||||||
|
header.dwSize = 124;
|
||||||
|
header.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE;
|
||||||
|
header.dwWidth = width;
|
||||||
|
header.dwHeight = height;
|
||||||
|
header.dwPitchOrLinearSize = DDS_size;
|
||||||
|
header.sPixelFormat.dwSize = 32;
|
||||||
|
header.sPixelFormat.dwFlags = DDPF_FOURCC;
|
||||||
|
if( (channels & 1) == 1 )
|
||||||
|
{
|
||||||
|
header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('1' << 24);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
header.sPixelFormat.dwFourCC = ('D' << 0) | ('X' << 8) | ('T' << 16) | ('5' << 24);
|
||||||
|
}
|
||||||
|
header.sCaps.dwCaps1 = DDSCAPS_TEXTURE;
|
||||||
|
/* write it out */
|
||||||
|
fout = fopen( filename, "wb");
|
||||||
|
fwrite( &header, sizeof( DDS_header ), 1, fout );
|
||||||
|
fwrite( DDS_data, 1, DDS_size, fout );
|
||||||
|
fclose( fout );
|
||||||
|
/* done */
|
||||||
|
free( DDS_data );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* convert_image_to_DXT1(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
int width, int height, int channels,
|
||||||
|
int *out_size )
|
||||||
|
{
|
||||||
|
unsigned char *compressed;
|
||||||
|
int i, j, x, y;
|
||||||
|
unsigned char ublock[16*3];
|
||||||
|
unsigned char cblock[8];
|
||||||
|
int index = 0, chan_step = 1;
|
||||||
|
int block_count = 0;
|
||||||
|
/* error check */
|
||||||
|
*out_size = 0;
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(NULL == uncompressed) ||
|
||||||
|
(channels < 1) || (channels > 4) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* for channels == 1 or 2, I do not step forward for R,G,B values */
|
||||||
|
if( channels < 3 )
|
||||||
|
{
|
||||||
|
chan_step = 0;
|
||||||
|
}
|
||||||
|
/* get the RAM for the compressed image
|
||||||
|
(8 bytes per 4x4 pixel block) */
|
||||||
|
*out_size = ((width+3) >> 2) * ((height+3) >> 2) * 8;
|
||||||
|
compressed = (unsigned char*)malloc( *out_size );
|
||||||
|
/* go through each block */
|
||||||
|
for( j = 0; j < height; j += 4 )
|
||||||
|
{
|
||||||
|
for( i = 0; i < width; i += 4 )
|
||||||
|
{
|
||||||
|
/* copy this block into a new one */
|
||||||
|
int idx = 0;
|
||||||
|
int mx = 4, my = 4;
|
||||||
|
if( j+4 >= height )
|
||||||
|
{
|
||||||
|
my = height - j;
|
||||||
|
}
|
||||||
|
if( i+4 >= width )
|
||||||
|
{
|
||||||
|
mx = width - i;
|
||||||
|
}
|
||||||
|
for( y = 0; y < my; ++y )
|
||||||
|
{
|
||||||
|
for( x = 0; x < mx; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
|
||||||
|
}
|
||||||
|
for( x = mx; x < 4; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = ublock[0];
|
||||||
|
ublock[idx++] = ublock[1];
|
||||||
|
ublock[idx++] = ublock[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( y = my; y < 4; ++y )
|
||||||
|
{
|
||||||
|
for( x = 0; x < 4; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = ublock[0];
|
||||||
|
ublock[idx++] = ublock[1];
|
||||||
|
ublock[idx++] = ublock[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* compress the block */
|
||||||
|
++block_count;
|
||||||
|
compress_DDS_color_block( 3, ublock, cblock );
|
||||||
|
/* copy the data from the block into the main block */
|
||||||
|
for( x = 0; x < 8; ++x )
|
||||||
|
{
|
||||||
|
compressed[index++] = cblock[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* convert_image_to_DXT5(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
int width, int height, int channels,
|
||||||
|
int *out_size )
|
||||||
|
{
|
||||||
|
unsigned char *compressed;
|
||||||
|
int i, j, x, y;
|
||||||
|
unsigned char ublock[16*4];
|
||||||
|
unsigned char cblock[8];
|
||||||
|
int index = 0, chan_step = 1;
|
||||||
|
int block_count = 0, has_alpha;
|
||||||
|
/* error check */
|
||||||
|
*out_size = 0;
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(NULL == uncompressed) ||
|
||||||
|
(channels < 1) || ( channels > 4) )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* for channels == 1 or 2, I do not step forward for R,G,B vales */
|
||||||
|
if( channels < 3 )
|
||||||
|
{
|
||||||
|
chan_step = 0;
|
||||||
|
}
|
||||||
|
/* # channels = 1 or 3 have no alpha, 2 & 4 do have alpha */
|
||||||
|
has_alpha = 1 - (channels & 1);
|
||||||
|
/* get the RAM for the compressed image
|
||||||
|
(16 bytes per 4x4 pixel block) */
|
||||||
|
*out_size = ((width+3) >> 2) * ((height+3) >> 2) * 16;
|
||||||
|
compressed = (unsigned char*)malloc( *out_size );
|
||||||
|
/* go through each block */
|
||||||
|
for( j = 0; j < height; j += 4 )
|
||||||
|
{
|
||||||
|
for( i = 0; i < width; i += 4 )
|
||||||
|
{
|
||||||
|
/* local variables, and my block counter */
|
||||||
|
int idx = 0;
|
||||||
|
int mx = 4, my = 4;
|
||||||
|
if( j+4 >= height )
|
||||||
|
{
|
||||||
|
my = height - j;
|
||||||
|
}
|
||||||
|
if( i+4 >= width )
|
||||||
|
{
|
||||||
|
mx = width - i;
|
||||||
|
}
|
||||||
|
for( y = 0; y < my; ++y )
|
||||||
|
{
|
||||||
|
for( x = 0; x < mx; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels];
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step];
|
||||||
|
ublock[idx++] = uncompressed[(j+y)*width*channels+(i+x)*channels+chan_step+chan_step];
|
||||||
|
ublock[idx++] =
|
||||||
|
has_alpha * uncompressed[(j+y)*width*channels+(i+x)*channels+channels-1]
|
||||||
|
+ (1-has_alpha)*255;
|
||||||
|
}
|
||||||
|
for( x = mx; x < 4; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = ublock[0];
|
||||||
|
ublock[idx++] = ublock[1];
|
||||||
|
ublock[idx++] = ublock[2];
|
||||||
|
ublock[idx++] = ublock[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for( y = my; y < 4; ++y )
|
||||||
|
{
|
||||||
|
for( x = 0; x < 4; ++x )
|
||||||
|
{
|
||||||
|
ublock[idx++] = ublock[0];
|
||||||
|
ublock[idx++] = ublock[1];
|
||||||
|
ublock[idx++] = ublock[2];
|
||||||
|
ublock[idx++] = ublock[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* now compress the alpha block */
|
||||||
|
compress_DDS_alpha_block( ublock, cblock );
|
||||||
|
/* copy the data from the compressed alpha block into the main buffer */
|
||||||
|
for( x = 0; x < 8; ++x )
|
||||||
|
{
|
||||||
|
compressed[index++] = cblock[x];
|
||||||
|
}
|
||||||
|
/* then compress the color block */
|
||||||
|
++block_count;
|
||||||
|
compress_DDS_color_block( 4, ublock, cblock );
|
||||||
|
/* copy the data from the compressed color block into the main buffer */
|
||||||
|
for( x = 0; x < 8; ++x )
|
||||||
|
{
|
||||||
|
compressed[index++] = cblock[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return compressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/********* Helper Functions *********/
|
||||||
|
int convert_bit_range( int c, int from_bits, int to_bits )
|
||||||
|
{
|
||||||
|
int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
|
||||||
|
return (b + (b >> from_bits)) >> from_bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
int rgb_to_565( int r, int g, int b )
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(convert_bit_range( r, 8, 5 ) << 11) |
|
||||||
|
(convert_bit_range( g, 8, 6 ) << 05) |
|
||||||
|
(convert_bit_range( b, 8, 5 ) << 00);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgb_888_from_565( unsigned int c, int *r, int *g, int *b )
|
||||||
|
{
|
||||||
|
*r = convert_bit_range( (c >> 11) & 31, 5, 8 );
|
||||||
|
*g = convert_bit_range( (c >> 05) & 63, 6, 8 );
|
||||||
|
*b = convert_bit_range( (c >> 00) & 31, 5, 8 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void compute_color_line_STDEV(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
int channels,
|
||||||
|
float point[3], float direction[3] )
|
||||||
|
{
|
||||||
|
const float inv_16 = 1.0f / 16.0f;
|
||||||
|
int i;
|
||||||
|
float sum_r = 0.0f, sum_g = 0.0f, sum_b = 0.0f;
|
||||||
|
float sum_rr = 0.0f, sum_gg = 0.0f, sum_bb = 0.0f;
|
||||||
|
float sum_rg = 0.0f, sum_rb = 0.0f, sum_gb = 0.0f;
|
||||||
|
/* calculate all data needed for the covariance matrix
|
||||||
|
( to compare with _rygdxt code) */
|
||||||
|
for( i = 0; i < 16*channels; i += channels )
|
||||||
|
{
|
||||||
|
sum_r += uncompressed[i+0];
|
||||||
|
sum_rr += uncompressed[i+0] * uncompressed[i+0];
|
||||||
|
sum_g += uncompressed[i+1];
|
||||||
|
sum_gg += uncompressed[i+1] * uncompressed[i+1];
|
||||||
|
sum_b += uncompressed[i+2];
|
||||||
|
sum_bb += uncompressed[i+2] * uncompressed[i+2];
|
||||||
|
sum_rg += uncompressed[i+0] * uncompressed[i+1];
|
||||||
|
sum_rb += uncompressed[i+0] * uncompressed[i+2];
|
||||||
|
sum_gb += uncompressed[i+1] * uncompressed[i+2];
|
||||||
|
}
|
||||||
|
/* convert the sums to averages */
|
||||||
|
sum_r *= inv_16;
|
||||||
|
sum_g *= inv_16;
|
||||||
|
sum_b *= inv_16;
|
||||||
|
/* and convert the squares to the squares of the value - avg_value */
|
||||||
|
sum_rr -= 16.0f * sum_r * sum_r;
|
||||||
|
sum_gg -= 16.0f * sum_g * sum_g;
|
||||||
|
sum_bb -= 16.0f * sum_b * sum_b;
|
||||||
|
sum_rg -= 16.0f * sum_r * sum_g;
|
||||||
|
sum_rb -= 16.0f * sum_r * sum_b;
|
||||||
|
sum_gb -= 16.0f * sum_g * sum_b;
|
||||||
|
/* the point on the color line is the average */
|
||||||
|
point[0] = sum_r;
|
||||||
|
point[1] = sum_g;
|
||||||
|
point[2] = sum_b;
|
||||||
|
#if USE_COV_MAT
|
||||||
|
/*
|
||||||
|
The following idea was from ryg.
|
||||||
|
(https://mollyrocket.com/forums/viewtopic.php?t=392)
|
||||||
|
The method worked great (less RMSE than mine) most of
|
||||||
|
the time, but had some issues handling some simple
|
||||||
|
boundary cases, like full green next to full red,
|
||||||
|
which would generate a covariance matrix like this:
|
||||||
|
|
||||||
|
| 1 -1 0 |
|
||||||
|
| -1 1 0 |
|
||||||
|
| 0 0 0 |
|
||||||
|
|
||||||
|
For a given starting vector, the power method can
|
||||||
|
generate all zeros! So no starting with {1,1,1}
|
||||||
|
as I was doing! This kind of error is still a
|
||||||
|
slight posibillity, but will be very rare.
|
||||||
|
*/
|
||||||
|
/* use the covariance matrix directly
|
||||||
|
(1st iteration, don't use all 1.0 values!) */
|
||||||
|
sum_r = 1.0f;
|
||||||
|
sum_g = 2.718281828f;
|
||||||
|
sum_b = 3.141592654f;
|
||||||
|
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
|
||||||
|
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
|
||||||
|
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
|
||||||
|
/* 2nd iteration, use results from the 1st guy */
|
||||||
|
sum_r = direction[0];
|
||||||
|
sum_g = direction[1];
|
||||||
|
sum_b = direction[2];
|
||||||
|
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
|
||||||
|
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
|
||||||
|
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
|
||||||
|
/* 3rd iteration, use results from the 2nd guy */
|
||||||
|
sum_r = direction[0];
|
||||||
|
sum_g = direction[1];
|
||||||
|
sum_b = direction[2];
|
||||||
|
direction[0] = sum_r*sum_rr + sum_g*sum_rg + sum_b*sum_rb;
|
||||||
|
direction[1] = sum_r*sum_rg + sum_g*sum_gg + sum_b*sum_gb;
|
||||||
|
direction[2] = sum_r*sum_rb + sum_g*sum_gb + sum_b*sum_bb;
|
||||||
|
#else
|
||||||
|
/* use my standard deviation method
|
||||||
|
(very robust, a tiny bit slower and less accurate) */
|
||||||
|
direction[0] = sqrt( sum_rr );
|
||||||
|
direction[1] = sqrt( sum_gg );
|
||||||
|
direction[2] = sqrt( sum_bb );
|
||||||
|
/* which has a greater component */
|
||||||
|
if( sum_gg > sum_rr )
|
||||||
|
{
|
||||||
|
/* green has greater component, so base the other signs off of green */
|
||||||
|
if( sum_rg < 0.0f )
|
||||||
|
{
|
||||||
|
direction[0] = -direction[0];
|
||||||
|
}
|
||||||
|
if( sum_gb < 0.0f )
|
||||||
|
{
|
||||||
|
direction[2] = -direction[2];
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* red has a greater component */
|
||||||
|
if( sum_rg < 0.0f )
|
||||||
|
{
|
||||||
|
direction[1] = -direction[1];
|
||||||
|
}
|
||||||
|
if( sum_rb < 0.0f )
|
||||||
|
{
|
||||||
|
direction[2] = -direction[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void LSE_master_colors_max_min(
|
||||||
|
int *cmax, int *cmin,
|
||||||
|
int channels,
|
||||||
|
const unsigned char *const uncompressed )
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
/* the master colors */
|
||||||
|
int c0[3], c1[3];
|
||||||
|
/* used for fitting the line */
|
||||||
|
float sum_x[] = { 0.0f, 0.0f, 0.0f };
|
||||||
|
float sum_x2[] = { 0.0f, 0.0f, 0.0f };
|
||||||
|
float dot_max = 1.0f, dot_min = -1.0f;
|
||||||
|
float vec_len2 = 0.0f;
|
||||||
|
float dot;
|
||||||
|
/* error check */
|
||||||
|
if( (channels < 3) || (channels > 4) )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
compute_color_line_STDEV( uncompressed, channels, sum_x, sum_x2 );
|
||||||
|
vec_len2 = 1.0f / ( 0.00001f +
|
||||||
|
sum_x2[0]*sum_x2[0] + sum_x2[1]*sum_x2[1] + sum_x2[2]*sum_x2[2] );
|
||||||
|
/* finding the max and min vector values */
|
||||||
|
dot_max =
|
||||||
|
(
|
||||||
|
sum_x2[0] * uncompressed[0] +
|
||||||
|
sum_x2[1] * uncompressed[1] +
|
||||||
|
sum_x2[2] * uncompressed[2]
|
||||||
|
);
|
||||||
|
dot_min = dot_max;
|
||||||
|
for( i = 1; i < 16; ++i )
|
||||||
|
{
|
||||||
|
dot =
|
||||||
|
(
|
||||||
|
sum_x2[0] * uncompressed[i*channels+0] +
|
||||||
|
sum_x2[1] * uncompressed[i*channels+1] +
|
||||||
|
sum_x2[2] * uncompressed[i*channels+2]
|
||||||
|
);
|
||||||
|
if( dot < dot_min )
|
||||||
|
{
|
||||||
|
dot_min = dot;
|
||||||
|
} else if( dot > dot_max )
|
||||||
|
{
|
||||||
|
dot_max = dot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* and the offset (from the average location) */
|
||||||
|
dot = sum_x2[0]*sum_x[0] + sum_x2[1]*sum_x[1] + sum_x2[2]*sum_x[2];
|
||||||
|
dot_min -= dot;
|
||||||
|
dot_max -= dot;
|
||||||
|
/* post multiply by the scaling factor */
|
||||||
|
dot_min *= vec_len2;
|
||||||
|
dot_max *= vec_len2;
|
||||||
|
/* OK, build the master colors */
|
||||||
|
for( i = 0; i < 3; ++i )
|
||||||
|
{
|
||||||
|
/* color 0 */
|
||||||
|
c0[i] = (int)(0.5f + sum_x[i] + dot_max * sum_x2[i]);
|
||||||
|
if( c0[i] < 0 )
|
||||||
|
{
|
||||||
|
c0[i] = 0;
|
||||||
|
} else if( c0[i] > 255 )
|
||||||
|
{
|
||||||
|
c0[i] = 255;
|
||||||
|
}
|
||||||
|
/* color 1 */
|
||||||
|
c1[i] = (int)(0.5f + sum_x[i] + dot_min * sum_x2[i]);
|
||||||
|
if( c1[i] < 0 )
|
||||||
|
{
|
||||||
|
c1[i] = 0;
|
||||||
|
} else if( c1[i] > 255 )
|
||||||
|
{
|
||||||
|
c1[i] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* down_sample (with rounding?) */
|
||||||
|
i = rgb_to_565( c0[0], c0[1], c0[2] );
|
||||||
|
j = rgb_to_565( c1[0], c1[1], c1[2] );
|
||||||
|
if( i > j )
|
||||||
|
{
|
||||||
|
*cmax = i;
|
||||||
|
*cmin = j;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
*cmax = j;
|
||||||
|
*cmin = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compress_DDS_color_block
|
||||||
|
(
|
||||||
|
int channels,
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
unsigned char compressed[8]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* variables */
|
||||||
|
int i;
|
||||||
|
int next_bit;
|
||||||
|
int enc_c0, enc_c1;
|
||||||
|
int c0[4], c1[4];
|
||||||
|
float color_line[] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
||||||
|
float vec_len2 = 0.0f, dot_offset = 0.0f;
|
||||||
|
/* stupid order */
|
||||||
|
int swizzle4[] = { 0, 2, 3, 1 };
|
||||||
|
/* get the master colors */
|
||||||
|
LSE_master_colors_max_min( &enc_c0, &enc_c1, channels, uncompressed );
|
||||||
|
/* store the 565 color 0 and color 1 */
|
||||||
|
compressed[0] = (enc_c0 >> 0) & 255;
|
||||||
|
compressed[1] = (enc_c0 >> 8) & 255;
|
||||||
|
compressed[2] = (enc_c1 >> 0) & 255;
|
||||||
|
compressed[3] = (enc_c1 >> 8) & 255;
|
||||||
|
/* zero out the compressed data */
|
||||||
|
compressed[4] = 0;
|
||||||
|
compressed[5] = 0;
|
||||||
|
compressed[6] = 0;
|
||||||
|
compressed[7] = 0;
|
||||||
|
/* reconstitute the master color vectors */
|
||||||
|
rgb_888_from_565( enc_c0, &c0[0], &c0[1], &c0[2] );
|
||||||
|
rgb_888_from_565( enc_c1, &c1[0], &c1[1], &c1[2] );
|
||||||
|
/* the new vector */
|
||||||
|
vec_len2 = 0.0f;
|
||||||
|
for( i = 0; i < 3; ++i )
|
||||||
|
{
|
||||||
|
color_line[i] = (float)(c1[i] - c0[i]);
|
||||||
|
vec_len2 += color_line[i] * color_line[i];
|
||||||
|
}
|
||||||
|
if( vec_len2 > 0.0f )
|
||||||
|
{
|
||||||
|
vec_len2 = 1.0f / vec_len2;
|
||||||
|
}
|
||||||
|
/* pre-proform the scaling */
|
||||||
|
color_line[0] *= vec_len2;
|
||||||
|
color_line[1] *= vec_len2;
|
||||||
|
color_line[2] *= vec_len2;
|
||||||
|
/* compute the offset (constant) portion of the dot product */
|
||||||
|
dot_offset = color_line[0]*c0[0] + color_line[1]*c0[1] + color_line[2]*c0[2];
|
||||||
|
/* store the rest of the bits */
|
||||||
|
next_bit = 8*4;
|
||||||
|
for( i = 0; i < 16; ++i )
|
||||||
|
{
|
||||||
|
/* find the dot product of this color, to place it on the line
|
||||||
|
(should be [-1,1]) */
|
||||||
|
int next_value = 0;
|
||||||
|
float dot_product =
|
||||||
|
color_line[0] * uncompressed[i*channels+0] +
|
||||||
|
color_line[1] * uncompressed[i*channels+1] +
|
||||||
|
color_line[2] * uncompressed[i*channels+2] -
|
||||||
|
dot_offset;
|
||||||
|
/* map to [0,3] */
|
||||||
|
next_value = (int)( dot_product * 3.0f + 0.5f );
|
||||||
|
if( next_value > 3 )
|
||||||
|
{
|
||||||
|
next_value = 3;
|
||||||
|
} else if( next_value < 0 )
|
||||||
|
{
|
||||||
|
next_value = 0;
|
||||||
|
}
|
||||||
|
/* OK, store this value */
|
||||||
|
compressed[next_bit >> 3] |= swizzle4[ next_value ] << (next_bit & 7);
|
||||||
|
next_bit += 2;
|
||||||
|
}
|
||||||
|
/* done compressing to DXT1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
compress_DDS_alpha_block
|
||||||
|
(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
unsigned char compressed[8]
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* variables */
|
||||||
|
int i;
|
||||||
|
int next_bit;
|
||||||
|
int a0, a1;
|
||||||
|
float scale_me;
|
||||||
|
/* stupid order */
|
||||||
|
int swizzle8[] = { 1, 7, 6, 5, 4, 3, 2, 0 };
|
||||||
|
/* get the alpha limits (a0 > a1) */
|
||||||
|
a0 = a1 = uncompressed[3];
|
||||||
|
for( i = 4+3; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
if( uncompressed[i] > a0 )
|
||||||
|
{
|
||||||
|
a0 = uncompressed[i];
|
||||||
|
} else if( uncompressed[i] < a1 )
|
||||||
|
{
|
||||||
|
a1 = uncompressed[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* store those limits, and zero the rest of the compressed dataset */
|
||||||
|
compressed[0] = a0;
|
||||||
|
compressed[1] = a1;
|
||||||
|
/* zero out the compressed data */
|
||||||
|
compressed[2] = 0;
|
||||||
|
compressed[3] = 0;
|
||||||
|
compressed[4] = 0;
|
||||||
|
compressed[5] = 0;
|
||||||
|
compressed[6] = 0;
|
||||||
|
compressed[7] = 0;
|
||||||
|
/* store the all of the alpha values */
|
||||||
|
next_bit = 8*2;
|
||||||
|
scale_me = 7.9999f / (a0 - a1);
|
||||||
|
for( i = 3; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
/* convert this alpha value to a 3 bit number */
|
||||||
|
int svalue;
|
||||||
|
int value = (int)((uncompressed[i] - a1) * scale_me);
|
||||||
|
svalue = swizzle8[ value&7 ];
|
||||||
|
/* OK, store this value, start with the 1st byte */
|
||||||
|
compressed[next_bit >> 3] |= svalue << (next_bit & 7);
|
||||||
|
if( (next_bit & 7) > 5 )
|
||||||
|
{
|
||||||
|
/* spans 2 bytes, fill in the start of the 2nd byte */
|
||||||
|
compressed[1 + (next_bit >> 3)] |= svalue >> (8 - (next_bit & 7) );
|
||||||
|
}
|
||||||
|
next_bit += 3;
|
||||||
|
}
|
||||||
|
/* done compressing to DXT1 */
|
||||||
|
}
|
123
cw 11/src/SOIL/image_DXT.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
Jonathan Dummer
|
||||||
|
2007-07-31-10.32
|
||||||
|
|
||||||
|
simple DXT compression / decompression code
|
||||||
|
|
||||||
|
public domain
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HEADER_IMAGE_DXT
|
||||||
|
#define HEADER_IMAGE_DXT
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an image from an array of unsigned chars (RGB or RGBA) to
|
||||||
|
DXT1 or DXT5, then saves the converted image to disk.
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
save_image_as_DDS
|
||||||
|
(
|
||||||
|
const char *filename,
|
||||||
|
int width, int height, int channels,
|
||||||
|
const unsigned char *const data
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
take an image and convert it to DXT1 (no alpha)
|
||||||
|
**/
|
||||||
|
unsigned char*
|
||||||
|
convert_image_to_DXT1
|
||||||
|
(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
int width, int height, int channels,
|
||||||
|
int *out_size
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
take an image and convert it to DXT5 (with alpha)
|
||||||
|
**/
|
||||||
|
unsigned char*
|
||||||
|
convert_image_to_DXT5
|
||||||
|
(
|
||||||
|
const unsigned char *const uncompressed,
|
||||||
|
int width, int height, int channels,
|
||||||
|
int *out_size
|
||||||
|
);
|
||||||
|
|
||||||
|
/** A bunch of DirectDraw Surface structures and flags **/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned int dwMagic;
|
||||||
|
unsigned int dwSize;
|
||||||
|
unsigned int dwFlags;
|
||||||
|
unsigned int dwHeight;
|
||||||
|
unsigned int dwWidth;
|
||||||
|
unsigned int dwPitchOrLinearSize;
|
||||||
|
unsigned int dwDepth;
|
||||||
|
unsigned int dwMipMapCount;
|
||||||
|
unsigned int dwReserved1[ 11 ];
|
||||||
|
|
||||||
|
/* DDPIXELFORMAT */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int dwSize;
|
||||||
|
unsigned int dwFlags;
|
||||||
|
unsigned int dwFourCC;
|
||||||
|
unsigned int dwRGBBitCount;
|
||||||
|
unsigned int dwRBitMask;
|
||||||
|
unsigned int dwGBitMask;
|
||||||
|
unsigned int dwBBitMask;
|
||||||
|
unsigned int dwAlphaBitMask;
|
||||||
|
}
|
||||||
|
sPixelFormat;
|
||||||
|
|
||||||
|
/* DDCAPS2 */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned int dwCaps1;
|
||||||
|
unsigned int dwCaps2;
|
||||||
|
unsigned int dwDDSX;
|
||||||
|
unsigned int dwReserved;
|
||||||
|
}
|
||||||
|
sCaps;
|
||||||
|
unsigned int dwReserved2;
|
||||||
|
}
|
||||||
|
DDS_header ;
|
||||||
|
|
||||||
|
/* the following constants were copied directly off the MSDN website */
|
||||||
|
|
||||||
|
/* The dwFlags member of the original DDSURFACEDESC2 structure
|
||||||
|
can be set to one or more of the following values. */
|
||||||
|
#define DDSD_CAPS 0x00000001
|
||||||
|
#define DDSD_HEIGHT 0x00000002
|
||||||
|
#define DDSD_WIDTH 0x00000004
|
||||||
|
#define DDSD_PITCH 0x00000008
|
||||||
|
#define DDSD_PIXELFORMAT 0x00001000
|
||||||
|
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||||
|
#define DDSD_LINEARSIZE 0x00080000
|
||||||
|
#define DDSD_DEPTH 0x00800000
|
||||||
|
|
||||||
|
/* DirectDraw Pixel Format */
|
||||||
|
#define DDPF_ALPHAPIXELS 0x00000001
|
||||||
|
#define DDPF_FOURCC 0x00000004
|
||||||
|
#define DDPF_RGB 0x00000040
|
||||||
|
|
||||||
|
/* The dwCaps1 member of the DDSCAPS2 structure can be
|
||||||
|
set to one or more of the following values. */
|
||||||
|
#define DDSCAPS_COMPLEX 0x00000008
|
||||||
|
#define DDSCAPS_TEXTURE 0x00001000
|
||||||
|
#define DDSCAPS_MIPMAP 0x00400000
|
||||||
|
|
||||||
|
/* The dwCaps2 member of the DDSCAPS2 structure can be
|
||||||
|
set to one or more of the following values. */
|
||||||
|
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||||
|
#define DDSCAPS2_VOLUME 0x00200000
|
||||||
|
|
||||||
|
#endif /* HEADER_IMAGE_DXT */
|
435
cw 11/src/SOIL/image_helper.c
Normal file
@ -0,0 +1,435 @@
|
|||||||
|
/*
|
||||||
|
Jonathan Dummer
|
||||||
|
|
||||||
|
image helper functions
|
||||||
|
|
||||||
|
MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "image_helper.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
/* Upscaling the image uses simple bilinear interpolation */
|
||||||
|
int
|
||||||
|
up_scale_image
|
||||||
|
(
|
||||||
|
const unsigned char* const orig,
|
||||||
|
int width, int height, int channels,
|
||||||
|
unsigned char* resampled,
|
||||||
|
int resampled_width, int resampled_height
|
||||||
|
)
|
||||||
|
{
|
||||||
|
float dx, dy;
|
||||||
|
int x, y, c;
|
||||||
|
|
||||||
|
/* error(s) check */
|
||||||
|
if ( (width < 1) || (height < 1) ||
|
||||||
|
(resampled_width < 2) || (resampled_height < 2) ||
|
||||||
|
(channels < 1) ||
|
||||||
|
(NULL == orig) || (NULL == resampled) )
|
||||||
|
{
|
||||||
|
/* signify badness */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
for each given pixel in the new map, find the exact location
|
||||||
|
from the original map which would contribute to this guy
|
||||||
|
*/
|
||||||
|
dx = (width - 1.0f) / (resampled_width - 1.0f);
|
||||||
|
dy = (height - 1.0f) / (resampled_height - 1.0f);
|
||||||
|
for ( y = 0; y < resampled_height; ++y )
|
||||||
|
{
|
||||||
|
/* find the base y index and fractional offset from that */
|
||||||
|
float sampley = y * dy;
|
||||||
|
int inty = (int)sampley;
|
||||||
|
/* if( inty < 0 ) { inty = 0; } else */
|
||||||
|
if( inty > height - 2 ) { inty = height - 2; }
|
||||||
|
sampley -= inty;
|
||||||
|
for ( x = 0; x < resampled_width; ++x )
|
||||||
|
{
|
||||||
|
float samplex = x * dx;
|
||||||
|
int intx = (int)samplex;
|
||||||
|
int base_index;
|
||||||
|
/* find the base x index and fractional offset from that */
|
||||||
|
/* if( intx < 0 ) { intx = 0; } else */
|
||||||
|
if( intx > width - 2 ) { intx = width - 2; }
|
||||||
|
samplex -= intx;
|
||||||
|
/* base index into the original image */
|
||||||
|
base_index = (inty * width + intx) * channels;
|
||||||
|
for ( c = 0; c < channels; ++c )
|
||||||
|
{
|
||||||
|
/* do the sampling */
|
||||||
|
float value = 0.5f;
|
||||||
|
value += orig[base_index]
|
||||||
|
*(1.0f-samplex)*(1.0f-sampley);
|
||||||
|
value += orig[base_index+channels]
|
||||||
|
*(samplex)*(1.0f-sampley);
|
||||||
|
value += orig[base_index+width*channels]
|
||||||
|
*(1.0f-samplex)*(sampley);
|
||||||
|
value += orig[base_index+width*channels+channels]
|
||||||
|
*(samplex)*(sampley);
|
||||||
|
/* move to the next channel */
|
||||||
|
++base_index;
|
||||||
|
/* save the new value */
|
||||||
|
resampled[y*resampled_width*channels+x*channels+c] =
|
||||||
|
(unsigned char)(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* done */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
mipmap_image
|
||||||
|
(
|
||||||
|
const unsigned char* const orig,
|
||||||
|
int width, int height, int channels,
|
||||||
|
unsigned char* resampled,
|
||||||
|
int block_size_x, int block_size_y
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int mip_width, mip_height;
|
||||||
|
int i, j, c;
|
||||||
|
|
||||||
|
/* error check */
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(channels < 1) || (orig == NULL) ||
|
||||||
|
(resampled == NULL) ||
|
||||||
|
(block_size_x < 1) || (block_size_y < 1) )
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mip_width = width / block_size_x;
|
||||||
|
mip_height = height / block_size_y;
|
||||||
|
if( mip_width < 1 )
|
||||||
|
{
|
||||||
|
mip_width = 1;
|
||||||
|
}
|
||||||
|
if( mip_height < 1 )
|
||||||
|
{
|
||||||
|
mip_height = 1;
|
||||||
|
}
|
||||||
|
for( j = 0; j < mip_height; ++j )
|
||||||
|
{
|
||||||
|
for( i = 0; i < mip_width; ++i )
|
||||||
|
{
|
||||||
|
for( c = 0; c < channels; ++c )
|
||||||
|
{
|
||||||
|
const int index = (j*block_size_y)*width*channels + (i*block_size_x)*channels + c;
|
||||||
|
int sum_value;
|
||||||
|
int u,v;
|
||||||
|
int u_block = block_size_x;
|
||||||
|
int v_block = block_size_y;
|
||||||
|
int block_area;
|
||||||
|
/* do a bit of checking so we don't over-run the boundaries
|
||||||
|
(necessary for non-square textures!) */
|
||||||
|
if( block_size_x * (i+1) > width )
|
||||||
|
{
|
||||||
|
u_block = width - i*block_size_y;
|
||||||
|
}
|
||||||
|
if( block_size_y * (j+1) > height )
|
||||||
|
{
|
||||||
|
v_block = height - j*block_size_y;
|
||||||
|
}
|
||||||
|
block_area = u_block*v_block;
|
||||||
|
/* for this pixel, see what the average
|
||||||
|
of all the values in the block are.
|
||||||
|
note: start the sum at the rounding value, not at 0 */
|
||||||
|
sum_value = block_area >> 1;
|
||||||
|
for( v = 0; v < v_block; ++v )
|
||||||
|
for( u = 0; u < u_block; ++u )
|
||||||
|
{
|
||||||
|
sum_value += orig[index + v*width*channels + u*channels];
|
||||||
|
}
|
||||||
|
resampled[j*mip_width*channels + i*channels + c] = sum_value / block_area;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
scale_image_RGB_to_NTSC_safe
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const float scale_lo = 16.0f - 0.499f;
|
||||||
|
const float scale_hi = 235.0f + 0.499f;
|
||||||
|
int i, j;
|
||||||
|
int nc = channels;
|
||||||
|
unsigned char scale_LUT[256];
|
||||||
|
/* error check */
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(channels < 1) || (orig == NULL) )
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* set up the scaling Look Up Table */
|
||||||
|
for( i = 0; i < 256; ++i )
|
||||||
|
{
|
||||||
|
scale_LUT[i] = (unsigned char)((scale_hi - scale_lo) * i / 255.0f + scale_lo);
|
||||||
|
}
|
||||||
|
/* for channels = 2 or 4, ignore the alpha component */
|
||||||
|
nc -= 1 - (channels & 1);
|
||||||
|
/* OK, go through the image and scale any non-alpha components */
|
||||||
|
for( i = 0; i < width*height*channels; i += channels )
|
||||||
|
{
|
||||||
|
for( j = 0; j < nc; ++j )
|
||||||
|
{
|
||||||
|
orig[i+j] = scale_LUT[orig[i+j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char clamp_byte( int x ) { return ( (x) < 0 ? (0) : ( (x) > 255 ? 255 : (x) ) ); }
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function takes the RGB components of the image
|
||||||
|
and converts them into YCoCg. 3 components will be
|
||||||
|
re-ordered to CoYCg (for optimum DXT1 compression),
|
||||||
|
while 4 components will be ordered CoCgAY (for DXT5
|
||||||
|
compression).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
convert_RGB_to_YCoCg
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/* error check */
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(channels < 3) || (channels > 4) ||
|
||||||
|
(orig == NULL) )
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* do the conversion */
|
||||||
|
if( channels == 3 )
|
||||||
|
{
|
||||||
|
for( i = 0; i < width*height*3; i += 3 )
|
||||||
|
{
|
||||||
|
int r = orig[i+0];
|
||||||
|
int g = (orig[i+1] + 1) >> 1;
|
||||||
|
int b = orig[i+2];
|
||||||
|
int tmp = (2 + r + b) >> 2;
|
||||||
|
/* Co */
|
||||||
|
orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
|
||||||
|
/* Y */
|
||||||
|
orig[i+1] = clamp_byte( g + tmp );
|
||||||
|
/* Cg */
|
||||||
|
orig[i+2] = clamp_byte( 128 + g - tmp );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
for( i = 0; i < width*height*4; i += 4 )
|
||||||
|
{
|
||||||
|
int r = orig[i+0];
|
||||||
|
int g = (orig[i+1] + 1) >> 1;
|
||||||
|
int b = orig[i+2];
|
||||||
|
unsigned char a = orig[i+3];
|
||||||
|
int tmp = (2 + r + b) >> 2;
|
||||||
|
/* Co */
|
||||||
|
orig[i+0] = clamp_byte( 128 + ((r - b + 1) >> 1) );
|
||||||
|
/* Cg */
|
||||||
|
orig[i+1] = clamp_byte( 128 + g - tmp );
|
||||||
|
/* Alpha */
|
||||||
|
orig[i+2] = a;
|
||||||
|
/* Y */
|
||||||
|
orig[i+3] = clamp_byte( g + tmp );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* done */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function takes the YCoCg components of the image
|
||||||
|
and converts them into RGB. See above.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
convert_YCoCg_to_RGB
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
/* error check */
|
||||||
|
if( (width < 1) || (height < 1) ||
|
||||||
|
(channels < 3) || (channels > 4) ||
|
||||||
|
(orig == NULL) )
|
||||||
|
{
|
||||||
|
/* nothing to do */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* do the conversion */
|
||||||
|
if( channels == 3 )
|
||||||
|
{
|
||||||
|
for( i = 0; i < width*height*3; i += 3 )
|
||||||
|
{
|
||||||
|
int co = orig[i+0] - 128;
|
||||||
|
int y = orig[i+1];
|
||||||
|
int cg = orig[i+2] - 128;
|
||||||
|
/* R */
|
||||||
|
orig[i+0] = clamp_byte( y + co - cg );
|
||||||
|
/* G */
|
||||||
|
orig[i+1] = clamp_byte( y + cg );
|
||||||
|
/* B */
|
||||||
|
orig[i+2] = clamp_byte( y - co - cg );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
for( i = 0; i < width*height*4; i += 4 )
|
||||||
|
{
|
||||||
|
int co = orig[i+0] - 128;
|
||||||
|
int cg = orig[i+1] - 128;
|
||||||
|
unsigned char a = orig[i+2];
|
||||||
|
int y = orig[i+3];
|
||||||
|
/* R */
|
||||||
|
orig[i+0] = clamp_byte( y + co - cg );
|
||||||
|
/* G */
|
||||||
|
orig[i+1] = clamp_byte( y + cg );
|
||||||
|
/* B */
|
||||||
|
orig[i+2] = clamp_byte( y - co - cg );
|
||||||
|
/* A */
|
||||||
|
orig[i+3] = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* done */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
find_max_RGBE
|
||||||
|
(
|
||||||
|
unsigned char *image,
|
||||||
|
int width, int height
|
||||||
|
)
|
||||||
|
{
|
||||||
|
float max_val = 0.0f;
|
||||||
|
unsigned char *img = image;
|
||||||
|
int i, j;
|
||||||
|
for( i = width * height; i > 0; --i )
|
||||||
|
{
|
||||||
|
/* float scale = powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||||
|
float scale = ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||||
|
for( j = 0; j < 3; ++j )
|
||||||
|
{
|
||||||
|
if( img[j] * scale > max_val )
|
||||||
|
{
|
||||||
|
max_val = img[j] * scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* next pixel */
|
||||||
|
img += 4;
|
||||||
|
}
|
||||||
|
return max_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RGBE_to_RGBdivA
|
||||||
|
(
|
||||||
|
unsigned char *image,
|
||||||
|
int width, int height,
|
||||||
|
int rescale_to_max
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* local variables */
|
||||||
|
int i, iv;
|
||||||
|
unsigned char *img = image;
|
||||||
|
float scale = 1.0f;
|
||||||
|
/* error check */
|
||||||
|
if( (!image) || (width < 1) || (height < 1) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* convert (note: no negative numbers, but 0.0 is possible) */
|
||||||
|
if( rescale_to_max )
|
||||||
|
{
|
||||||
|
scale = 255.0f / find_max_RGBE( image, width, height );
|
||||||
|
}
|
||||||
|
for( i = width * height; i > 0; --i )
|
||||||
|
{
|
||||||
|
/* decode this pixel, and find the max */
|
||||||
|
float r,g,b,e, m;
|
||||||
|
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||||
|
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||||
|
r = e * img[0];
|
||||||
|
g = e * img[1];
|
||||||
|
b = e * img[2];
|
||||||
|
m = (r > g) ? r : g;
|
||||||
|
m = (b > m) ? b : m;
|
||||||
|
/* and encode it into RGBdivA */
|
||||||
|
iv = (m != 0.0f) ? (int)(255.0f / m) : 1.0f;
|
||||||
|
iv = (iv < 1) ? 1 : iv;
|
||||||
|
img[3] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * r + 0.5f);
|
||||||
|
img[0] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * g + 0.5f);
|
||||||
|
img[1] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * b + 0.5f);
|
||||||
|
img[2] = (iv > 255) ? 255 : iv;
|
||||||
|
/* and on to the next pixel */
|
||||||
|
img += 4;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
RGBE_to_RGBdivA2
|
||||||
|
(
|
||||||
|
unsigned char *image,
|
||||||
|
int width, int height,
|
||||||
|
int rescale_to_max
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* local variables */
|
||||||
|
int i, iv;
|
||||||
|
unsigned char *img = image;
|
||||||
|
float scale = 1.0f;
|
||||||
|
/* error check */
|
||||||
|
if( (!image) || (width < 1) || (height < 1) )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* convert (note: no negative numbers, but 0.0 is possible) */
|
||||||
|
if( rescale_to_max )
|
||||||
|
{
|
||||||
|
scale = 255.0f * 255.0f / find_max_RGBE( image, width, height );
|
||||||
|
}
|
||||||
|
for( i = width * height; i > 0; --i )
|
||||||
|
{
|
||||||
|
/* decode this pixel, and find the max */
|
||||||
|
float r,g,b,e, m;
|
||||||
|
/* e = scale * powf( 2.0f, img[3] - 128.0f ) / 255.0f; */
|
||||||
|
e = scale * ldexp( 1.0f / 255.0f, (int)(img[3]) - 128 );
|
||||||
|
r = e * img[0];
|
||||||
|
g = e * img[1];
|
||||||
|
b = e * img[2];
|
||||||
|
m = (r > g) ? r : g;
|
||||||
|
m = (b > m) ? b : m;
|
||||||
|
/* and encode it into RGBdivA */
|
||||||
|
iv = (m != 0.0f) ? (int)sqrtf( 255.0f * 255.0f / m ) : 1.0f;
|
||||||
|
iv = (iv < 1) ? 1 : iv;
|
||||||
|
img[3] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * img[3] * r / 255.0f + 0.5f);
|
||||||
|
img[0] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * img[3] * g / 255.0f + 0.5f);
|
||||||
|
img[1] = (iv > 255) ? 255 : iv;
|
||||||
|
iv = (int)(img[3] * img[3] * b / 255.0f + 0.5f);
|
||||||
|
img[2] = (iv > 255) ? 255 : iv;
|
||||||
|
/* and on to the next pixel */
|
||||||
|
img += 4;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
115
cw 11/src/SOIL/image_helper.h
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
Jonathan Dummer
|
||||||
|
|
||||||
|
Image helper functions
|
||||||
|
|
||||||
|
MIT license
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HEADER_IMAGE_HELPER
|
||||||
|
#define HEADER_IMAGE_HELPER
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function upscales an image.
|
||||||
|
Not to be used to create MIPmaps,
|
||||||
|
but to make it square,
|
||||||
|
or to make it a power-of-two sized.
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
up_scale_image
|
||||||
|
(
|
||||||
|
const unsigned char* const orig,
|
||||||
|
int width, int height, int channels,
|
||||||
|
unsigned char* resampled,
|
||||||
|
int resampled_width, int resampled_height
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function downscales an image.
|
||||||
|
Used for creating MIPmaps,
|
||||||
|
the incoming image should be a
|
||||||
|
power-of-two sized.
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
mipmap_image
|
||||||
|
(
|
||||||
|
const unsigned char* const orig,
|
||||||
|
int width, int height, int channels,
|
||||||
|
unsigned char* resampled,
|
||||||
|
int block_size_x, int block_size_y
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function takes the RGB components of the image
|
||||||
|
and scales each channel from [0,255] to [16,235].
|
||||||
|
This makes the colors "Safe" for display on NTSC
|
||||||
|
displays. Note that this is _NOT_ a good idea for
|
||||||
|
loading images like normal- or height-maps!
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
scale_image_RGB_to_NTSC_safe
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function takes the RGB components of the image
|
||||||
|
and converts them into YCoCg. 3 components will be
|
||||||
|
re-ordered to CoYCg (for optimum DXT1 compression),
|
||||||
|
while 4 components will be ordered CoCgAY (for DXT5
|
||||||
|
compression).
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
convert_RGB_to_YCoCg
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function takes the YCoCg components of the image
|
||||||
|
and converts them into RGB. See above.
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
convert_YCoCg_to_RGB
|
||||||
|
(
|
||||||
|
unsigned char* orig,
|
||||||
|
int width, int height, int channels
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an HDR image from an array
|
||||||
|
of unsigned chars (RGBE) to RGBdivA
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
RGBE_to_RGBdivA
|
||||||
|
(
|
||||||
|
unsigned char *image,
|
||||||
|
int width, int height,
|
||||||
|
int rescale_to_max
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Converts an HDR image from an array
|
||||||
|
of unsigned chars (RGBE) to RGBdivA2
|
||||||
|
\return 0 if failed, otherwise returns 1
|
||||||
|
**/
|
||||||
|
int
|
||||||
|
RGBE_to_RGBdivA2
|
||||||
|
(
|
||||||
|
unsigned char *image,
|
||||||
|
int width, int height,
|
||||||
|
int rescale_to_max
|
||||||
|
);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* HEADER_IMAGE_HELPER */
|
3682
cw 11/src/SOIL/stb_image_aug.c
Normal file
354
cw 11/src/SOIL/stb_image_aug.h
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
/* stbi-1.16 - public domain JPEG/PNG reader - http://nothings.org/stb_image.c
|
||||||
|
when you control the images you're loading
|
||||||
|
|
||||||
|
QUICK NOTES:
|
||||||
|
Primarily of interest to game developers and other people who can
|
||||||
|
avoid problematic images and only need the trivial interface
|
||||||
|
|
||||||
|
JPEG baseline (no JPEG progressive, no oddball channel decimations)
|
||||||
|
PNG non-interlaced
|
||||||
|
BMP non-1bpp, non-RLE
|
||||||
|
TGA (not sure what subset, if a subset)
|
||||||
|
PSD (composited view only, no extra channels)
|
||||||
|
HDR (radiance rgbE format)
|
||||||
|
writes BMP,TGA (define STBI_NO_WRITE to remove code)
|
||||||
|
decoded from memory or through stdio FILE (define STBI_NO_STDIO to remove code)
|
||||||
|
supports installable dequantizing-IDCT, YCbCr-to-RGB conversion (define STBI_SIMD)
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
stbi_info_*
|
||||||
|
|
||||||
|
history:
|
||||||
|
1.16 major bugfix - convert_format converted one too many pixels
|
||||||
|
1.15 initialize some fields for thread safety
|
||||||
|
1.14 fix threadsafe conversion bug; header-file-only version (#define STBI_HEADER_FILE_ONLY before including)
|
||||||
|
1.13 threadsafe
|
||||||
|
1.12 const qualifiers in the API
|
||||||
|
1.11 Support installable IDCT, colorspace conversion routines
|
||||||
|
1.10 Fixes for 64-bit (don't use "unsigned long")
|
||||||
|
optimized upsampling by Fabian "ryg" Giesen
|
||||||
|
1.09 Fix format-conversion for PSD code (bad global variables!)
|
||||||
|
1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz
|
||||||
|
1.07 attempt to fix C++ warning/errors again
|
||||||
|
1.06 attempt to fix C++ warning/errors again
|
||||||
|
1.05 fix TGA loading to return correct *comp and use good luminance calc
|
||||||
|
1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free
|
||||||
|
1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR
|
||||||
|
1.02 support for (subset of) HDR files, float interface for preferred access to them
|
||||||
|
1.01 fix bug: possible bug in handling right-side up bmps... not sure
|
||||||
|
fix bug: the stbi_bmp_load() and stbi_tga_load() functions didn't work at all
|
||||||
|
1.00 interface to zlib that skips zlib header
|
||||||
|
0.99 correct handling of alpha in palette
|
||||||
|
0.98 TGA loader by lonesock; dynamically add loaders (untested)
|
||||||
|
0.97 jpeg errors on too large a file; also catch another malloc failure
|
||||||
|
0.96 fix detection of invalid v value - particleman@mollyrocket forum
|
||||||
|
0.95 during header scan, seek to markers in case of padding
|
||||||
|
0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same
|
||||||
|
0.93 handle jpegtran output; verbose errors
|
||||||
|
0.92 read 4,8,16,24,32-bit BMP files of several formats
|
||||||
|
0.91 output 24-bit Windows 3.0 BMP files
|
||||||
|
0.90 fix a few more warnings; bump version number to approach 1.0
|
||||||
|
0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd
|
||||||
|
0.60 fix compiling as c++
|
||||||
|
0.59 fix warnings: merge Dave Moore's -Wall fixes
|
||||||
|
0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian
|
||||||
|
0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less
|
||||||
|
than 16 available
|
||||||
|
0.56 fix bug: zlib uncompressed mode len vs. nlen
|
||||||
|
0.55 fix bug: restart_interval not initialized to 0
|
||||||
|
0.54 allow NULL for 'int *comp'
|
||||||
|
0.53 fix bug in png 3->4; speedup png decoding
|
||||||
|
0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments
|
||||||
|
0.51 obey req_comp requests, 1-component jpegs return as 1-component,
|
||||||
|
on 'test' only check type, not whether we support this variant
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HEADER_STB_IMAGE_AUGMENTED
|
||||||
|
#define HEADER_STB_IMAGE_AUGMENTED
|
||||||
|
|
||||||
|
//// begin header file ////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Limitations:
|
||||||
|
// - no progressive/interlaced support (jpeg, png)
|
||||||
|
// - 8-bit samples only (jpeg, png)
|
||||||
|
// - not threadsafe
|
||||||
|
// - channel subsampling of at most 2 in each dimension (jpeg)
|
||||||
|
// - no delayed line count (jpeg) -- IJG doesn't support either
|
||||||
|
//
|
||||||
|
// Basic usage (see HDR discussion below):
|
||||||
|
// int x,y,n;
|
||||||
|
// unsigned char *data = stbi_load(filename, &x, &y, &n, 0);
|
||||||
|
// // ... process data if not NULL ...
|
||||||
|
// // ... x = width, y = height, n = # 8-bit components per pixel ...
|
||||||
|
// // ... replace '0' with '1'..'4' to force that many components per pixel
|
||||||
|
// stbi_image_free(data)
|
||||||
|
//
|
||||||
|
// Standard parameters:
|
||||||
|
// int *x -- outputs image width in pixels
|
||||||
|
// int *y -- outputs image height in pixels
|
||||||
|
// int *comp -- outputs # of image components in image file
|
||||||
|
// int req_comp -- if non-zero, # of image components requested in result
|
||||||
|
//
|
||||||
|
// The return value from an image loader is an 'unsigned char *' which points
|
||||||
|
// to the pixel data. The pixel data consists of *y scanlines of *x pixels,
|
||||||
|
// with each pixel consisting of N interleaved 8-bit components; the first
|
||||||
|
// pixel pointed to is top-left-most in the image. There is no padding between
|
||||||
|
// image scanlines or between pixels, regardless of format. The number of
|
||||||
|
// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise.
|
||||||
|
// If req_comp is non-zero, *comp has the number of components that _would_
|
||||||
|
// have been output otherwise. E.g. if you set req_comp to 4, you will always
|
||||||
|
// get RGBA output, but you can check *comp to easily see if it's opaque.
|
||||||
|
//
|
||||||
|
// An output image with N components has the following components interleaved
|
||||||
|
// in this order in each pixel:
|
||||||
|
//
|
||||||
|
// N=#comp components
|
||||||
|
// 1 grey
|
||||||
|
// 2 grey, alpha
|
||||||
|
// 3 red, green, blue
|
||||||
|
// 4 red, green, blue, alpha
|
||||||
|
//
|
||||||
|
// If image loading fails for any reason, the return value will be NULL,
|
||||||
|
// and *x, *y, *comp will be unchanged. The function stbi_failure_reason()
|
||||||
|
// can be queried for an extremely brief, end-user unfriendly explanation
|
||||||
|
// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid
|
||||||
|
// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly
|
||||||
|
// more user-friendly ones.
|
||||||
|
//
|
||||||
|
// Paletted PNG and BMP images are automatically depalettized.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// ===========================================================================
|
||||||
|
//
|
||||||
|
// HDR image support (disable by defining STBI_NO_HDR)
|
||||||
|
//
|
||||||
|
// stb_image now supports loading HDR images in general, and currently
|
||||||
|
// the Radiance .HDR file format, although the support is provided
|
||||||
|
// generically. You can still load any file through the existing interface;
|
||||||
|
// if you attempt to load an HDR file, it will be automatically remapped to
|
||||||
|
// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1;
|
||||||
|
// both of these constants can be reconfigured through this interface:
|
||||||
|
//
|
||||||
|
// stbi_hdr_to_ldr_gamma(2.2f);
|
||||||
|
// stbi_hdr_to_ldr_scale(1.0f);
|
||||||
|
//
|
||||||
|
// (note, do not use _inverse_ constants; stbi_image will invert them
|
||||||
|
// appropriately).
|
||||||
|
//
|
||||||
|
// Additionally, there is a new, parallel interface for loading files as
|
||||||
|
// (linear) floats to preserve the full dynamic range:
|
||||||
|
//
|
||||||
|
// float *data = stbi_loadf(filename, &x, &y, &n, 0);
|
||||||
|
//
|
||||||
|
// If you load LDR images through this interface, those images will
|
||||||
|
// be promoted to floating point values, run through the inverse of
|
||||||
|
// constants corresponding to the above:
|
||||||
|
//
|
||||||
|
// stbi_ldr_to_hdr_scale(1.0f);
|
||||||
|
// stbi_ldr_to_hdr_gamma(2.2f);
|
||||||
|
//
|
||||||
|
// Finally, given a filename (or an open file or memory block--see header
|
||||||
|
// file for details) containing image data, you can query for the "most
|
||||||
|
// appropriate" interface to use (that is, whether the image is HDR or
|
||||||
|
// not), using:
|
||||||
|
//
|
||||||
|
// stbi_is_hdr(char *filename);
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
#include <stdio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STBI_VERSION 1
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
STBI_default = 0, // only used for req_comp
|
||||||
|
|
||||||
|
STBI_grey = 1,
|
||||||
|
STBI_grey_alpha = 2,
|
||||||
|
STBI_rgb = 3,
|
||||||
|
STBI_rgb_alpha = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef unsigned char stbi_uc;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// WRITING API
|
||||||
|
|
||||||
|
#if !defined(STBI_NO_WRITE) && !defined(STBI_NO_STDIO)
|
||||||
|
// write a BMP/TGA file given tightly packed 'comp' channels (no padding, nor bmp-stride-padding)
|
||||||
|
// (you must include the appropriate extension in the filename).
|
||||||
|
// returns TRUE on success, FALSE if couldn't open file, error writing file
|
||||||
|
extern int stbi_write_bmp (char const *filename, int x, int y, int comp, void *data);
|
||||||
|
extern int stbi_write_tga (char const *filename, int x, int y, int comp, void *data);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// PRIMARY API - works on images of any type
|
||||||
|
|
||||||
|
// load image by filename, open file, or memory buffer
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||||
|
#endif
|
||||||
|
extern stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
// for stbi_load_from_file, file pointer is left pointing immediately after image
|
||||||
|
|
||||||
|
#ifndef STBI_NO_HDR
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
extern float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
|
||||||
|
extern void stbi_hdr_to_ldr_gamma(float gamma);
|
||||||
|
extern void stbi_hdr_to_ldr_scale(float scale);
|
||||||
|
|
||||||
|
extern void stbi_ldr_to_hdr_gamma(float gamma);
|
||||||
|
extern void stbi_ldr_to_hdr_scale(float scale);
|
||||||
|
|
||||||
|
#endif // STBI_NO_HDR
|
||||||
|
|
||||||
|
// get a VERY brief reason for failure
|
||||||
|
// NOT THREADSAFE
|
||||||
|
extern char *stbi_failure_reason (void);
|
||||||
|
|
||||||
|
// free the loaded image -- this is just free()
|
||||||
|
extern void stbi_image_free (void *retval_from_stbi_load);
|
||||||
|
|
||||||
|
// get image dimensions & components without fully decoding
|
||||||
|
extern int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_info (char const *filename, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_is_hdr (char const *filename);
|
||||||
|
extern int stbi_is_hdr_from_file(FILE *f);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ZLIB client - used by PNG, available for other purposes
|
||||||
|
|
||||||
|
extern char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen);
|
||||||
|
extern char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen);
|
||||||
|
extern int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||||
|
|
||||||
|
extern char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen);
|
||||||
|
extern int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen);
|
||||||
|
|
||||||
|
// TYPE-SPECIFIC ACCESS
|
||||||
|
|
||||||
|
// is it a jpeg?
|
||||||
|
extern int stbi_jpeg_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
extern stbi_uc *stbi_jpeg_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_jpeg_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern stbi_uc *stbi_jpeg_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_jpeg_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_jpeg_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
|
||||||
|
extern int stbi_jpeg_info (char const *filename, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_jpeg_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is it a png?
|
||||||
|
extern int stbi_png_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
extern stbi_uc *stbi_png_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_png_info_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp);
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern stbi_uc *stbi_png_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_png_info (char const *filename, int *x, int *y, int *comp);
|
||||||
|
extern int stbi_png_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_png_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern int stbi_png_info_from_file (FILE *f, int *x, int *y, int *comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is it a bmp?
|
||||||
|
extern int stbi_bmp_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
|
||||||
|
extern stbi_uc *stbi_bmp_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_bmp_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_bmp_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_bmp_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is it a tga?
|
||||||
|
extern int stbi_tga_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
|
||||||
|
extern stbi_uc *stbi_tga_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_tga_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_tga_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_tga_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is it a psd?
|
||||||
|
extern int stbi_psd_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
|
||||||
|
extern stbi_uc *stbi_psd_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_psd_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_psd_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_psd_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is it an hdr?
|
||||||
|
extern int stbi_hdr_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
|
||||||
|
extern float * stbi_hdr_load (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_hdr_load_rgbe (char const *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern float * stbi_hdr_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_hdr_test_file (FILE *f);
|
||||||
|
extern float * stbi_hdr_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_hdr_load_rgbe_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// define new loaders
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int (*test_memory)(stbi_uc const *buffer, int len);
|
||||||
|
stbi_uc * (*load_from_memory)(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
int (*test_file)(FILE *f);
|
||||||
|
stbi_uc * (*load_from_file)(FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
} stbi_loader;
|
||||||
|
|
||||||
|
// register a loader by filling out the above structure (you must defined ALL functions)
|
||||||
|
// returns 1 if added or already added, 0 if not added (too many loaders)
|
||||||
|
// NOT THREADSAFE
|
||||||
|
extern int stbi_register_loader(stbi_loader *loader);
|
||||||
|
|
||||||
|
// define faster low-level operations (typically SIMD support)
|
||||||
|
#if STBI_SIMD
|
||||||
|
typedef void (*stbi_idct_8x8)(uint8 *out, int out_stride, short data[64], unsigned short *dequantize);
|
||||||
|
// compute an integer IDCT on "input"
|
||||||
|
// input[x] = data[x] * dequantize[x]
|
||||||
|
// write results to 'out': 64 samples, each run of 8 spaced by 'out_stride'
|
||||||
|
// CLAMP results to 0..255
|
||||||
|
typedef void (*stbi_YCbCr_to_RGB_run)(uint8 *output, uint8 const *y, uint8 const *cb, uint8 const *cr, int count, int step);
|
||||||
|
// compute a conversion from YCbCr to RGB
|
||||||
|
// 'count' pixels
|
||||||
|
// write pixels to 'output'; each pixel is 'step' bytes (either 3 or 4; if 4, write '255' as 4th), order R,G,B
|
||||||
|
// y: Y input channel
|
||||||
|
// cb: Cb input channel; scale/biased to be 0..255
|
||||||
|
// cr: Cr input channel; scale/biased to be 0..255
|
||||||
|
|
||||||
|
extern void stbi_install_idct(stbi_idct_8x8 func);
|
||||||
|
extern void stbi_install_YCbCr_to_RGB(stbi_YCbCr_to_RGB_run func);
|
||||||
|
#endif // STBI_SIMD
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// end header file /////////////////////////////////////////////////////
|
||||||
|
#endif // STBI_INCLUDE_STB_IMAGE_H
|
21
cw 11/src/SOIL/stbi_DDS_aug.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
adding DDS loading support to stbi
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||||
|
#define HEADER_STB_IMAGE_DDS_AUGMENTATION
|
||||||
|
|
||||||
|
// is it a DDS file?
|
||||||
|
extern int stbi_dds_test_memory (stbi_uc const *buffer, int len);
|
||||||
|
|
||||||
|
extern stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp);
|
||||||
|
extern stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
extern int stbi_dds_test_file (FILE *f);
|
||||||
|
extern stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//// end header file /////////////////////////////////////////////////////
|
||||||
|
#endif // HEADER_STB_IMAGE_DDS_AUGMENTATION
|
511
cw 11/src/SOIL/stbi_DDS_aug_c.h
Normal file
@ -0,0 +1,511 @@
|
|||||||
|
|
||||||
|
/// DDS file support, does decoding, _not_ direct uploading
|
||||||
|
/// (use SOIL for that ;-)
|
||||||
|
|
||||||
|
/// A bunch of DirectDraw Surface structures and flags
|
||||||
|
typedef struct {
|
||||||
|
unsigned int dwMagic;
|
||||||
|
unsigned int dwSize;
|
||||||
|
unsigned int dwFlags;
|
||||||
|
unsigned int dwHeight;
|
||||||
|
unsigned int dwWidth;
|
||||||
|
unsigned int dwPitchOrLinearSize;
|
||||||
|
unsigned int dwDepth;
|
||||||
|
unsigned int dwMipMapCount;
|
||||||
|
unsigned int dwReserved1[ 11 ];
|
||||||
|
|
||||||
|
// DDPIXELFORMAT
|
||||||
|
struct {
|
||||||
|
unsigned int dwSize;
|
||||||
|
unsigned int dwFlags;
|
||||||
|
unsigned int dwFourCC;
|
||||||
|
unsigned int dwRGBBitCount;
|
||||||
|
unsigned int dwRBitMask;
|
||||||
|
unsigned int dwGBitMask;
|
||||||
|
unsigned int dwBBitMask;
|
||||||
|
unsigned int dwAlphaBitMask;
|
||||||
|
} sPixelFormat;
|
||||||
|
|
||||||
|
// DDCAPS2
|
||||||
|
struct {
|
||||||
|
unsigned int dwCaps1;
|
||||||
|
unsigned int dwCaps2;
|
||||||
|
unsigned int dwDDSX;
|
||||||
|
unsigned int dwReserved;
|
||||||
|
} sCaps;
|
||||||
|
unsigned int dwReserved2;
|
||||||
|
} DDS_header ;
|
||||||
|
|
||||||
|
// the following constants were copied directly off the MSDN website
|
||||||
|
|
||||||
|
// The dwFlags member of the original DDSURFACEDESC2 structure
|
||||||
|
// can be set to one or more of the following values.
|
||||||
|
#define DDSD_CAPS 0x00000001
|
||||||
|
#define DDSD_HEIGHT 0x00000002
|
||||||
|
#define DDSD_WIDTH 0x00000004
|
||||||
|
#define DDSD_PITCH 0x00000008
|
||||||
|
#define DDSD_PIXELFORMAT 0x00001000
|
||||||
|
#define DDSD_MIPMAPCOUNT 0x00020000
|
||||||
|
#define DDSD_LINEARSIZE 0x00080000
|
||||||
|
#define DDSD_DEPTH 0x00800000
|
||||||
|
|
||||||
|
// DirectDraw Pixel Format
|
||||||
|
#define DDPF_ALPHAPIXELS 0x00000001
|
||||||
|
#define DDPF_FOURCC 0x00000004
|
||||||
|
#define DDPF_RGB 0x00000040
|
||||||
|
|
||||||
|
// The dwCaps1 member of the DDSCAPS2 structure can be
|
||||||
|
// set to one or more of the following values.
|
||||||
|
#define DDSCAPS_COMPLEX 0x00000008
|
||||||
|
#define DDSCAPS_TEXTURE 0x00001000
|
||||||
|
#define DDSCAPS_MIPMAP 0x00400000
|
||||||
|
|
||||||
|
// The dwCaps2 member of the DDSCAPS2 structure can be
|
||||||
|
// set to one or more of the following values.
|
||||||
|
#define DDSCAPS2_CUBEMAP 0x00000200
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEX 0x00000400
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEX 0x00000800
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEY 0x00001000
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEY 0x00002000
|
||||||
|
#define DDSCAPS2_CUBEMAP_POSITIVEZ 0x00004000
|
||||||
|
#define DDSCAPS2_CUBEMAP_NEGATIVEZ 0x00008000
|
||||||
|
#define DDSCAPS2_VOLUME 0x00200000
|
||||||
|
|
||||||
|
static int dds_test(stbi *s)
|
||||||
|
{
|
||||||
|
// check the magic number
|
||||||
|
if (get8(s) != 'D') return 0;
|
||||||
|
if (get8(s) != 'D') return 0;
|
||||||
|
if (get8(s) != 'S') return 0;
|
||||||
|
if (get8(s) != ' ') return 0;
|
||||||
|
// check header size
|
||||||
|
if (get32le(s) != 124) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
int stbi_dds_test_file (FILE *f)
|
||||||
|
{
|
||||||
|
stbi s;
|
||||||
|
int r,n = ftell(f);
|
||||||
|
start_file(&s,f);
|
||||||
|
r = dds_test(&s);
|
||||||
|
fseek(f,n,SEEK_SET);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int stbi_dds_test_memory (stbi_uc const *buffer, int len)
|
||||||
|
{
|
||||||
|
stbi s;
|
||||||
|
start_mem(&s,buffer, len);
|
||||||
|
return dds_test(&s);
|
||||||
|
}
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
int stbi_convert_bit_range( int c, int from_bits, int to_bits )
|
||||||
|
{
|
||||||
|
int b = (1 << (from_bits - 1)) + c * ((1 << to_bits) - 1);
|
||||||
|
return (b + (b >> from_bits)) >> from_bits;
|
||||||
|
}
|
||||||
|
void stbi_rgb_888_from_565( unsigned int c, int *r, int *g, int *b )
|
||||||
|
{
|
||||||
|
*r = stbi_convert_bit_range( (c >> 11) & 31, 5, 8 );
|
||||||
|
*g = stbi_convert_bit_range( (c >> 05) & 63, 6, 8 );
|
||||||
|
*b = stbi_convert_bit_range( (c >> 00) & 31, 5, 8 );
|
||||||
|
}
|
||||||
|
void stbi_decode_DXT1_block(
|
||||||
|
unsigned char uncompressed[16*4],
|
||||||
|
unsigned char compressed[8] )
|
||||||
|
{
|
||||||
|
int next_bit = 4*8;
|
||||||
|
int i, r, g, b;
|
||||||
|
int c0, c1;
|
||||||
|
unsigned char decode_colors[4*4];
|
||||||
|
// find the 2 primary colors
|
||||||
|
c0 = compressed[0] + (compressed[1] << 8);
|
||||||
|
c1 = compressed[2] + (compressed[3] << 8);
|
||||||
|
stbi_rgb_888_from_565( c0, &r, &g, &b );
|
||||||
|
decode_colors[0] = r;
|
||||||
|
decode_colors[1] = g;
|
||||||
|
decode_colors[2] = b;
|
||||||
|
decode_colors[3] = 255;
|
||||||
|
stbi_rgb_888_from_565( c1, &r, &g, &b );
|
||||||
|
decode_colors[4] = r;
|
||||||
|
decode_colors[5] = g;
|
||||||
|
decode_colors[6] = b;
|
||||||
|
decode_colors[7] = 255;
|
||||||
|
if( c0 > c1 )
|
||||||
|
{
|
||||||
|
// no alpha, 2 interpolated colors
|
||||||
|
decode_colors[8] = (2*decode_colors[0] + decode_colors[4]) / 3;
|
||||||
|
decode_colors[9] = (2*decode_colors[1] + decode_colors[5]) / 3;
|
||||||
|
decode_colors[10] = (2*decode_colors[2] + decode_colors[6]) / 3;
|
||||||
|
decode_colors[11] = 255;
|
||||||
|
decode_colors[12] = (decode_colors[0] + 2*decode_colors[4]) / 3;
|
||||||
|
decode_colors[13] = (decode_colors[1] + 2*decode_colors[5]) / 3;
|
||||||
|
decode_colors[14] = (decode_colors[2] + 2*decode_colors[6]) / 3;
|
||||||
|
decode_colors[15] = 255;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// 1 interpolated color, alpha
|
||||||
|
decode_colors[8] = (decode_colors[0] + decode_colors[4]) / 2;
|
||||||
|
decode_colors[9] = (decode_colors[1] + decode_colors[5]) / 2;
|
||||||
|
decode_colors[10] = (decode_colors[2] + decode_colors[6]) / 2;
|
||||||
|
decode_colors[11] = 255;
|
||||||
|
decode_colors[12] = 0;
|
||||||
|
decode_colors[13] = 0;
|
||||||
|
decode_colors[14] = 0;
|
||||||
|
decode_colors[15] = 0;
|
||||||
|
}
|
||||||
|
// decode the block
|
||||||
|
for( i = 0; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 4;
|
||||||
|
next_bit += 2;
|
||||||
|
uncompressed[i+0] = decode_colors[idx+0];
|
||||||
|
uncompressed[i+1] = decode_colors[idx+1];
|
||||||
|
uncompressed[i+2] = decode_colors[idx+2];
|
||||||
|
uncompressed[i+3] = decode_colors[idx+3];
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
}
|
||||||
|
void stbi_decode_DXT23_alpha_block(
|
||||||
|
unsigned char uncompressed[16*4],
|
||||||
|
unsigned char compressed[8] )
|
||||||
|
{
|
||||||
|
int i, next_bit = 0;
|
||||||
|
// each alpha value gets 4 bits
|
||||||
|
for( i = 3; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
uncompressed[i] = stbi_convert_bit_range(
|
||||||
|
(compressed[next_bit>>3] >> (next_bit&7)) & 15,
|
||||||
|
4, 8 );
|
||||||
|
next_bit += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void stbi_decode_DXT45_alpha_block(
|
||||||
|
unsigned char uncompressed[16*4],
|
||||||
|
unsigned char compressed[8] )
|
||||||
|
{
|
||||||
|
int i, next_bit = 8*2;
|
||||||
|
unsigned char decode_alpha[8];
|
||||||
|
// each alpha value gets 3 bits, and the 1st 2 bytes are the range
|
||||||
|
decode_alpha[0] = compressed[0];
|
||||||
|
decode_alpha[1] = compressed[1];
|
||||||
|
if( decode_alpha[0] > decode_alpha[1] )
|
||||||
|
{
|
||||||
|
// 6 step intermediate
|
||||||
|
decode_alpha[2] = (6*decode_alpha[0] + 1*decode_alpha[1]) / 7;
|
||||||
|
decode_alpha[3] = (5*decode_alpha[0] + 2*decode_alpha[1]) / 7;
|
||||||
|
decode_alpha[4] = (4*decode_alpha[0] + 3*decode_alpha[1]) / 7;
|
||||||
|
decode_alpha[5] = (3*decode_alpha[0] + 4*decode_alpha[1]) / 7;
|
||||||
|
decode_alpha[6] = (2*decode_alpha[0] + 5*decode_alpha[1]) / 7;
|
||||||
|
decode_alpha[7] = (1*decode_alpha[0] + 6*decode_alpha[1]) / 7;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// 4 step intermediate, pluss full and none
|
||||||
|
decode_alpha[2] = (4*decode_alpha[0] + 1*decode_alpha[1]) / 5;
|
||||||
|
decode_alpha[3] = (3*decode_alpha[0] + 2*decode_alpha[1]) / 5;
|
||||||
|
decode_alpha[4] = (2*decode_alpha[0] + 3*decode_alpha[1]) / 5;
|
||||||
|
decode_alpha[5] = (1*decode_alpha[0] + 4*decode_alpha[1]) / 5;
|
||||||
|
decode_alpha[6] = 0;
|
||||||
|
decode_alpha[7] = 255;
|
||||||
|
}
|
||||||
|
for( i = 3; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
int idx = 0, bit;
|
||||||
|
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
||||||
|
idx += bit << 0;
|
||||||
|
++next_bit;
|
||||||
|
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
||||||
|
idx += bit << 1;
|
||||||
|
++next_bit;
|
||||||
|
bit = (compressed[next_bit>>3] >> (next_bit&7)) & 1;
|
||||||
|
idx += bit << 2;
|
||||||
|
++next_bit;
|
||||||
|
uncompressed[i] = decode_alpha[idx & 7];
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
}
|
||||||
|
void stbi_decode_DXT_color_block(
|
||||||
|
unsigned char uncompressed[16*4],
|
||||||
|
unsigned char compressed[8] )
|
||||||
|
{
|
||||||
|
int next_bit = 4*8;
|
||||||
|
int i, r, g, b;
|
||||||
|
int c0, c1;
|
||||||
|
unsigned char decode_colors[4*3];
|
||||||
|
// find the 2 primary colors
|
||||||
|
c0 = compressed[0] + (compressed[1] << 8);
|
||||||
|
c1 = compressed[2] + (compressed[3] << 8);
|
||||||
|
stbi_rgb_888_from_565( c0, &r, &g, &b );
|
||||||
|
decode_colors[0] = r;
|
||||||
|
decode_colors[1] = g;
|
||||||
|
decode_colors[2] = b;
|
||||||
|
stbi_rgb_888_from_565( c1, &r, &g, &b );
|
||||||
|
decode_colors[3] = r;
|
||||||
|
decode_colors[4] = g;
|
||||||
|
decode_colors[5] = b;
|
||||||
|
// Like DXT1, but no choicees:
|
||||||
|
// no alpha, 2 interpolated colors
|
||||||
|
decode_colors[6] = (2*decode_colors[0] + decode_colors[3]) / 3;
|
||||||
|
decode_colors[7] = (2*decode_colors[1] + decode_colors[4]) / 3;
|
||||||
|
decode_colors[8] = (2*decode_colors[2] + decode_colors[5]) / 3;
|
||||||
|
decode_colors[9] = (decode_colors[0] + 2*decode_colors[3]) / 3;
|
||||||
|
decode_colors[10] = (decode_colors[1] + 2*decode_colors[4]) / 3;
|
||||||
|
decode_colors[11] = (decode_colors[2] + 2*decode_colors[5]) / 3;
|
||||||
|
// decode the block
|
||||||
|
for( i = 0; i < 16*4; i += 4 )
|
||||||
|
{
|
||||||
|
int idx = ((compressed[next_bit>>3] >> (next_bit & 7)) & 3) * 3;
|
||||||
|
next_bit += 2;
|
||||||
|
uncompressed[i+0] = decode_colors[idx+0];
|
||||||
|
uncompressed[i+1] = decode_colors[idx+1];
|
||||||
|
uncompressed[i+2] = decode_colors[idx+2];
|
||||||
|
}
|
||||||
|
// done
|
||||||
|
}
|
||||||
|
static stbi_uc *dds_load(stbi *s, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
// all variables go up front
|
||||||
|
stbi_uc *dds_data = NULL;
|
||||||
|
stbi_uc block[16*4];
|
||||||
|
stbi_uc compressed[8];
|
||||||
|
int flags, DXT_family;
|
||||||
|
int has_alpha, has_mipmap;
|
||||||
|
int is_compressed, cubemap_faces;
|
||||||
|
int block_pitch, num_blocks;
|
||||||
|
DDS_header header;
|
||||||
|
int i, sz, cf;
|
||||||
|
// load the header
|
||||||
|
if( sizeof( DDS_header ) != 128 )
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
getn( s, (stbi_uc*)(&header), 128 );
|
||||||
|
// and do some checking
|
||||||
|
if( header.dwMagic != (('D' << 0) | ('D' << 8) | ('S' << 16) | (' ' << 24)) ) return NULL;
|
||||||
|
if( header.dwSize != 124 ) return NULL;
|
||||||
|
flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
||||||
|
if( (header.dwFlags & flags) != flags ) return NULL;
|
||||||
|
/* According to the MSDN spec, the dwFlags should contain
|
||||||
|
DDSD_LINEARSIZE if it's compressed, or DDSD_PITCH if
|
||||||
|
uncompressed. Some DDS writers do not conform to the
|
||||||
|
spec, so I need to make my reader more tolerant */
|
||||||
|
if( header.sPixelFormat.dwSize != 32 ) return NULL;
|
||||||
|
flags = DDPF_FOURCC | DDPF_RGB;
|
||||||
|
if( (header.sPixelFormat.dwFlags & flags) == 0 ) return NULL;
|
||||||
|
if( (header.sCaps.dwCaps1 & DDSCAPS_TEXTURE) == 0 ) return NULL;
|
||||||
|
// get the image data
|
||||||
|
s->img_x = header.dwWidth;
|
||||||
|
s->img_y = header.dwHeight;
|
||||||
|
s->img_n = 4;
|
||||||
|
is_compressed = (header.sPixelFormat.dwFlags & DDPF_FOURCC) / DDPF_FOURCC;
|
||||||
|
has_alpha = (header.sPixelFormat.dwFlags & DDPF_ALPHAPIXELS) / DDPF_ALPHAPIXELS;
|
||||||
|
has_mipmap = (header.sCaps.dwCaps1 & DDSCAPS_MIPMAP) && (header.dwMipMapCount > 1);
|
||||||
|
cubemap_faces = (header.sCaps.dwCaps2 & DDSCAPS2_CUBEMAP) / DDSCAPS2_CUBEMAP;
|
||||||
|
/* I need cubemaps to have square faces */
|
||||||
|
cubemap_faces &= (s->img_x == s->img_y);
|
||||||
|
cubemap_faces *= 5;
|
||||||
|
cubemap_faces += 1;
|
||||||
|
block_pitch = (s->img_x+3) >> 2;
|
||||||
|
num_blocks = block_pitch * ((s->img_y+3) >> 2);
|
||||||
|
/* let the user know what's going on */
|
||||||
|
*x = s->img_x;
|
||||||
|
*y = s->img_y;
|
||||||
|
*comp = s->img_n;
|
||||||
|
/* is this uncompressed? */
|
||||||
|
if( is_compressed )
|
||||||
|
{
|
||||||
|
/* compressed */
|
||||||
|
// note: header.sPixelFormat.dwFourCC is something like (('D'<<0)|('X'<<8)|('T'<<16)|('1'<<24))
|
||||||
|
DXT_family = 1 + (header.sPixelFormat.dwFourCC >> 24) - '1';
|
||||||
|
if( (DXT_family < 1) || (DXT_family > 5) ) return NULL;
|
||||||
|
/* check the expected size...oops, nevermind...
|
||||||
|
those non-compliant writers leave
|
||||||
|
dwPitchOrLinearSize == 0 */
|
||||||
|
// passed all the tests, get the RAM for decoding
|
||||||
|
sz = (s->img_x)*(s->img_y)*4*cubemap_faces;
|
||||||
|
dds_data = (unsigned char*)malloc( sz );
|
||||||
|
/* do this once for each face */
|
||||||
|
for( cf = 0; cf < cubemap_faces; ++ cf )
|
||||||
|
{
|
||||||
|
// now read and decode all the blocks
|
||||||
|
for( i = 0; i < num_blocks; ++i )
|
||||||
|
{
|
||||||
|
// where are we?
|
||||||
|
int bx, by, bw=4, bh=4;
|
||||||
|
int ref_x = 4 * (i % block_pitch);
|
||||||
|
int ref_y = 4 * (i / block_pitch);
|
||||||
|
// get the next block's worth of compressed data, and decompress it
|
||||||
|
if( DXT_family == 1 )
|
||||||
|
{
|
||||||
|
// DXT1
|
||||||
|
getn( s, compressed, 8 );
|
||||||
|
stbi_decode_DXT1_block( block, compressed );
|
||||||
|
} else if( DXT_family < 4 )
|
||||||
|
{
|
||||||
|
// DXT2/3
|
||||||
|
getn( s, compressed, 8 );
|
||||||
|
stbi_decode_DXT23_alpha_block ( block, compressed );
|
||||||
|
getn( s, compressed, 8 );
|
||||||
|
stbi_decode_DXT_color_block ( block, compressed );
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// DXT4/5
|
||||||
|
getn( s, compressed, 8 );
|
||||||
|
stbi_decode_DXT45_alpha_block ( block, compressed );
|
||||||
|
getn( s, compressed, 8 );
|
||||||
|
stbi_decode_DXT_color_block ( block, compressed );
|
||||||
|
}
|
||||||
|
// is this a partial block?
|
||||||
|
if( ref_x + 4 > s->img_x )
|
||||||
|
{
|
||||||
|
bw = s->img_x - ref_x;
|
||||||
|
}
|
||||||
|
if( ref_y + 4 > s->img_y )
|
||||||
|
{
|
||||||
|
bh = s->img_y - ref_y;
|
||||||
|
}
|
||||||
|
// now drop our decompressed data into the buffer
|
||||||
|
for( by = 0; by < bh; ++by )
|
||||||
|
{
|
||||||
|
int idx = 4*((ref_y+by+cf*s->img_x)*s->img_x + ref_x);
|
||||||
|
for( bx = 0; bx < bw*4; ++bx )
|
||||||
|
{
|
||||||
|
|
||||||
|
dds_data[idx+bx] = block[by*16+bx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* done reading and decoding the main image...
|
||||||
|
skip MIPmaps if present */
|
||||||
|
if( has_mipmap )
|
||||||
|
{
|
||||||
|
int block_size = 16;
|
||||||
|
if( DXT_family == 1 )
|
||||||
|
{
|
||||||
|
block_size = 8;
|
||||||
|
}
|
||||||
|
for( i = 1; i < header.dwMipMapCount; ++i )
|
||||||
|
{
|
||||||
|
int mx = s->img_x >> (i + 2);
|
||||||
|
int my = s->img_y >> (i + 2);
|
||||||
|
if( mx < 1 )
|
||||||
|
{
|
||||||
|
mx = 1;
|
||||||
|
}
|
||||||
|
if( my < 1 )
|
||||||
|
{
|
||||||
|
my = 1;
|
||||||
|
}
|
||||||
|
skip( s, mx*my*block_size );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}/* per cubemap face */
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
/* uncompressed */
|
||||||
|
DXT_family = 0;
|
||||||
|
s->img_n = 3;
|
||||||
|
if( has_alpha )
|
||||||
|
{
|
||||||
|
s->img_n = 4;
|
||||||
|
}
|
||||||
|
*comp = s->img_n;
|
||||||
|
sz = s->img_x*s->img_y*s->img_n*cubemap_faces;
|
||||||
|
dds_data = (unsigned char*)malloc( sz );
|
||||||
|
/* do this once for each face */
|
||||||
|
for( cf = 0; cf < cubemap_faces; ++ cf )
|
||||||
|
{
|
||||||
|
/* read the main image for this face */
|
||||||
|
getn( s, &dds_data[cf*s->img_x*s->img_y*s->img_n], s->img_x*s->img_y*s->img_n );
|
||||||
|
/* done reading and decoding the main image...
|
||||||
|
skip MIPmaps if present */
|
||||||
|
if( has_mipmap )
|
||||||
|
{
|
||||||
|
for( i = 1; i < header.dwMipMapCount; ++i )
|
||||||
|
{
|
||||||
|
int mx = s->img_x >> i;
|
||||||
|
int my = s->img_y >> i;
|
||||||
|
if( mx < 1 )
|
||||||
|
{
|
||||||
|
mx = 1;
|
||||||
|
}
|
||||||
|
if( my < 1 )
|
||||||
|
{
|
||||||
|
my = 1;
|
||||||
|
}
|
||||||
|
skip( s, mx*my*s->img_n );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* data was BGR, I need it RGB */
|
||||||
|
for( i = 0; i < sz; i += s->img_n )
|
||||||
|
{
|
||||||
|
unsigned char temp = dds_data[i];
|
||||||
|
dds_data[i] = dds_data[i+2];
|
||||||
|
dds_data[i+2] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* finished decompressing into RGBA,
|
||||||
|
adjust the y size if we have a cubemap
|
||||||
|
note: sz is already up to date */
|
||||||
|
s->img_y *= cubemap_faces;
|
||||||
|
*y = s->img_y;
|
||||||
|
// did the user want something else, or
|
||||||
|
// see if all the alpha values are 255 (i.e. no transparency)
|
||||||
|
has_alpha = 0;
|
||||||
|
if( s->img_n == 4)
|
||||||
|
{
|
||||||
|
for( i = 3; (i < sz) && (has_alpha == 0); i += 4 )
|
||||||
|
{
|
||||||
|
has_alpha |= (dds_data[i] < 255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( (req_comp <= 4) && (req_comp >= 1) )
|
||||||
|
{
|
||||||
|
// user has some requirements, meet them
|
||||||
|
if( req_comp != s->img_n )
|
||||||
|
{
|
||||||
|
dds_data = convert_format( dds_data, s->img_n, req_comp, s->img_x, s->img_y );
|
||||||
|
*comp = s->img_n;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// user had no requirements, only drop to RGB is no alpha
|
||||||
|
if( (has_alpha == 0) && (s->img_n == 4) )
|
||||||
|
{
|
||||||
|
dds_data = convert_format( dds_data, 4, 3, s->img_x, s->img_y );
|
||||||
|
*comp = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// OK, done
|
||||||
|
return dds_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef STBI_NO_STDIO
|
||||||
|
stbi_uc *stbi_dds_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
stbi s;
|
||||||
|
start_file(&s,f);
|
||||||
|
return dds_load(&s,x,y,comp,req_comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
stbi_uc *stbi_dds_load (char *filename, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
stbi_uc *data;
|
||||||
|
FILE *f = fopen(filename, "rb");
|
||||||
|
if (!f) return NULL;
|
||||||
|
data = stbi_dds_load_from_file(f,x,y,comp,req_comp);
|
||||||
|
fclose(f);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
stbi_uc *stbi_dds_load_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
|
||||||
|
{
|
||||||
|
stbi s;
|
||||||
|
start_mem(&s,buffer, len);
|
||||||
|
return dds_load(&s,x,y,comp,req_comp);
|
||||||
|
}
|
102
cw 11/src/Shader_Loader.cpp
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#include "Shader_Loader.h"
|
||||||
|
#include<iostream>
|
||||||
|
#include<fstream>
|
||||||
|
#include<vector>
|
||||||
|
|
||||||
|
using namespace Core;
|
||||||
|
|
||||||
|
Shader_Loader::Shader_Loader(void){}
|
||||||
|
Shader_Loader::~Shader_Loader(void){}
|
||||||
|
|
||||||
|
std::string Shader_Loader::ReadShader(char *filename)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string shaderCode;
|
||||||
|
std::ifstream file(filename, std::ios::in);
|
||||||
|
|
||||||
|
if (!file.good())
|
||||||
|
{
|
||||||
|
std::cout << "Can't read file " << filename << std::endl;
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
file.seekg(0, std::ios::end);
|
||||||
|
shaderCode.resize((unsigned int)file.tellg());
|
||||||
|
file.seekg(0, std::ios::beg);
|
||||||
|
file.read(&shaderCode[0], shaderCode.size());
|
||||||
|
file.close();
|
||||||
|
return shaderCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Shader_Loader::CreateShader(GLenum shaderType, std::string
|
||||||
|
source, char* shaderName)
|
||||||
|
{
|
||||||
|
|
||||||
|
int compile_result = 0;
|
||||||
|
|
||||||
|
GLuint shader = glCreateShader(shaderType);
|
||||||
|
const char *shader_code_ptr = source.c_str();
|
||||||
|
const int shader_code_size = source.size();
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, &shader_code_ptr, &shader_code_size);
|
||||||
|
glCompileShader(shader);
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &compile_result);
|
||||||
|
|
||||||
|
//sprawdz bledy
|
||||||
|
if (compile_result == GL_FALSE)
|
||||||
|
{
|
||||||
|
|
||||||
|
int info_log_length = 0;
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||||
|
std::vector<char> shader_log(info_log_length);
|
||||||
|
glGetShaderInfoLog(shader, info_log_length, NULL, &shader_log[0]);
|
||||||
|
std::cout << "ERROR compiling shader: " << shaderName << std::endl << &shader_log[0] << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Shader_Loader::CreateProgram(char* vertexShaderFilename,
|
||||||
|
char* fragmentShaderFilename)
|
||||||
|
{
|
||||||
|
|
||||||
|
//wczytaj shadery
|
||||||
|
std::string vertex_shader_code = ReadShader(vertexShaderFilename);
|
||||||
|
std::string fragment_shader_code = ReadShader(fragmentShaderFilename);
|
||||||
|
|
||||||
|
GLuint vertex_shader = CreateShader(GL_VERTEX_SHADER, vertex_shader_code, "vertex shader");
|
||||||
|
GLuint fragment_shader = CreateShader(GL_FRAGMENT_SHADER, fragment_shader_code, "fragment shader");
|
||||||
|
|
||||||
|
int link_result = 0;
|
||||||
|
//stworz shader
|
||||||
|
GLuint program = glCreateProgram();
|
||||||
|
glAttachShader(program, vertex_shader);
|
||||||
|
glAttachShader(program, fragment_shader);
|
||||||
|
|
||||||
|
glLinkProgram(program);
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &link_result);
|
||||||
|
//sprawdz bledy w linkerze
|
||||||
|
if (link_result == GL_FALSE)
|
||||||
|
{
|
||||||
|
|
||||||
|
int info_log_length = 0;
|
||||||
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||||
|
std::vector<char> program_log(info_log_length);
|
||||||
|
glGetProgramInfoLog(program, info_log_length, NULL, &program_log[0]);
|
||||||
|
std::cout << "Shader Loader : LINK ERROR" << std::endl << &program_log[0] << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDetachShader(program, vertex_shader);
|
||||||
|
glDetachShader(program, fragment_shader);
|
||||||
|
glDeleteShader(vertex_shader);
|
||||||
|
glDeleteShader(fragment_shader);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader_Loader::DeleteProgram( GLuint program )
|
||||||
|
{
|
||||||
|
glDeleteProgram(program);
|
||||||
|
}
|
29
cw 11/src/Shader_Loader.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glew.h"
|
||||||
|
#include "freeglut.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
|
||||||
|
class Shader_Loader
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::string ReadShader(char *filename);
|
||||||
|
GLuint CreateShader(GLenum shaderType,
|
||||||
|
std::string source,
|
||||||
|
char* shaderName);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Shader_Loader(void);
|
||||||
|
~Shader_Loader(void);
|
||||||
|
GLuint CreateProgram(char* VertexShaderFilename,
|
||||||
|
char* FragmentShaderFilename);
|
||||||
|
|
||||||
|
void DeleteProgram(GLuint program);
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
37
cw 11/src/Texture.cpp
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <vector>
|
||||||
|
#include "SOIL/SOIL.h"
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
|
||||||
|
GLuint Core::LoadTexture( const char * filepath )
|
||||||
|
{
|
||||||
|
GLuint id;
|
||||||
|
glGenTextures(1, &id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
|
|
||||||
|
int w, h;
|
||||||
|
unsigned char* image = SOIL_load_image(filepath, &w, &h, 0, SOIL_LOAD_RGBA);
|
||||||
|
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||||
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
SOIL_free_image_data(image);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit)
|
||||||
|
{
|
||||||
|
glUniform1i(glGetUniformLocation(programID, shaderVariableName), textureUnit);
|
||||||
|
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
||||||
|
}
|
15
cw 11/src/Texture.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "glew.h"
|
||||||
|
#include "freeglut.h"
|
||||||
|
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
GLuint LoadTexture(const char * filepath);
|
||||||
|
|
||||||
|
// textureID - identyfikator tekstury otrzymany z funkcji LoadTexture
|
||||||
|
// shaderVariableName - nazwa zmiennej typu 'sampler2D' w shaderze, z ktora ma zostac powiazana tekstura
|
||||||
|
// programID - identyfikator aktualnego programu karty graficznej
|
||||||
|
// textureUnit - indeks jednostki teksturujacej - liczba od 0 do 7. Jezeli uzywa sie wielu tekstur w jednym shaderze, to kazda z nich nalezy powiazac z inna jednostka.
|
||||||
|
void SetActiveTexture(GLuint textureID, const char * shaderVariableName, GLuint programID, int textureUnit);
|
||||||
|
}
|
483
cw 11/src/ex_10_1.hpp
Normal file
@ -0,0 +1,483 @@
|
|||||||
|
#include "glew.h"
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "ext.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "Shader_Loader.h"
|
||||||
|
#include "Render_Utils.h"
|
||||||
|
|
||||||
|
#include "glew.h"
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "gtx/matrix_decompose.hpp"
|
||||||
|
#include "gtx/transform.hpp"
|
||||||
|
#include "ext.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
|
#include "Shader_Loader.h"
|
||||||
|
#include "Render_Utils.h"
|
||||||
|
#include "Camera.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include "Box.cpp"
|
||||||
|
#include <assimp/Importer.hpp>
|
||||||
|
#include <assimp/scene.h>
|
||||||
|
#include <assimp/postprocess.h>
|
||||||
|
//#include <assimp/pbrmaterial.h>
|
||||||
|
|
||||||
|
#include "Texture.h"
|
||||||
|
|
||||||
|
//obliczyc kwateriony nastepnie interpolowac.
|
||||||
|
|
||||||
|
glm::quat rotationCamera = glm::quat(1, 0, 0, 0);
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<glm::vec3> keyPoints({
|
||||||
|
glm::vec3(-711.745f, 89.9272f, -626.537f),
|
||||||
|
//glm::vec3(-711.745f, 91.9272f, -606.537f),
|
||||||
|
glm::vec3(-687.635f, 100.428f, -503.943f),
|
||||||
|
//glm::vec3(-721.365f, 103.613f, -598.223f),
|
||||||
|
glm::vec3(-667.635f, 128.428f, -433.943f),
|
||||||
|
glm::vec3(-547.654f, 180.445f, -401.846f),
|
||||||
|
glm::vec3(-365.357f, 261.268f, -304.93f),
|
||||||
|
glm::vec3(-346.51f, 146.605f, -85.3702f),
|
||||||
|
glm::vec3(-461.105f, 120.275f, 115.596f),
|
||||||
|
glm::vec3(-507.395f, 76.497f, 338.408f),
|
||||||
|
glm::vec3(-181.343f, 58.7994f, 403.918f),
|
||||||
|
glm::vec3(-148.073f, 72.7797f, 522.283f),
|
||||||
|
glm::vec3(-76.8437f, 85.1488f, 524.396f),
|
||||||
|
glm::vec3(-30.0008f, 81.3007f, 367.907f),
|
||||||
|
glm::vec3(20.808f, 117.73f, 109.607f),
|
||||||
|
glm::vec3(8.72873f, 135.983f, -130.435f),
|
||||||
|
glm::vec3(8.72873f, 115.983f, -132.435f),
|
||||||
|
glm::vec3(8.72873f, 104.983f, -132.435f),
|
||||||
|
glm::vec3(8.72873f, 100.983f, -132.435f),
|
||||||
|
});
|
||||||
|
|
||||||
|
std::vector<glm::quat> keyRotation;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
bool FOLLOW_CAR = false;
|
||||||
|
|
||||||
|
GLuint program;
|
||||||
|
GLuint programTextureSpecular;
|
||||||
|
GLuint programTexture;
|
||||||
|
GLuint programSun;
|
||||||
|
Core::Shader_Loader shaderLoader;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Core::RenderContext armContext;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Core::RenderContext> armContexts;
|
||||||
|
|
||||||
|
std::vector<Core::Node> city;
|
||||||
|
|
||||||
|
std::vector<Core::Node> car;
|
||||||
|
|
||||||
|
|
||||||
|
float cameraAngle = 0;
|
||||||
|
glm::vec3 cameraSide;
|
||||||
|
glm::vec3 cameraDir;
|
||||||
|
glm::vec3 cameraPos = keyPoints[0] + glm::vec3(0, 10, -5);
|
||||||
|
|
||||||
|
glm::mat4 cameraMatrix, perspectiveMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
glm::vec3 lightDir = glm::normalize(glm::vec3(1, 1, 1));
|
||||||
|
|
||||||
|
float old_x, old_y = -1;
|
||||||
|
float delta_x, delta_y = 0;
|
||||||
|
//glm::quat rotation_y;
|
||||||
|
//glm::quat rotation_x;// = glm::angleAxis(glm::pi<float>() * 0.25f, glm::vec3(0, 1, 0));
|
||||||
|
glm::quat rotation_y = glm::normalize(glm::angleAxis(209 * 0.03f, glm::vec3(1, 0, 0)));
|
||||||
|
glm::quat rotation_x = glm::normalize(glm::angleAxis(307 * 0.03f, glm::vec3(0, 1, 0)));
|
||||||
|
float dy = 0;
|
||||||
|
float dx = 0;
|
||||||
|
|
||||||
|
void processInput(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
float angleSpeed = 0.5f;
|
||||||
|
float moveSpeed = 2.f;
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
|
||||||
|
glfwSetWindowShouldClose(window, true);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_Z) == GLFW_PRESS) {
|
||||||
|
cameraAngle -= angleSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_X) == GLFW_PRESS) {
|
||||||
|
cameraAngle += angleSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) {
|
||||||
|
cameraPos += cameraDir * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) {
|
||||||
|
cameraPos -= cameraDir * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS) {
|
||||||
|
cameraPos += cameraSide * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS) {
|
||||||
|
cameraPos -= cameraSide * moveSpeed;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS) {
|
||||||
|
cameraPos = keyPoints[0] + glm::vec3(0, 3, 0); index = 0;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS) {
|
||||||
|
index = (index + 1) % keyPoints.size(); cameraPos = keyPoints[index] + glm::vec3(-3, 20, -3);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_Q) == GLFW_PRESS) {
|
||||||
|
index = (keyPoints.size() + index - 1) % keyPoints.size(); cameraPos = keyPoints[index] + glm::vec3(-3, 20, -3);
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) {
|
||||||
|
FOLLOW_CAR = !FOLLOW_CAR;
|
||||||
|
}
|
||||||
|
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) {
|
||||||
|
cameraPos = glm::vec3(0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
double x, y;
|
||||||
|
glfwGetCursorPos(window, &x, &y);
|
||||||
|
|
||||||
|
if (old_x >= 0) {
|
||||||
|
delta_x = x - old_x;
|
||||||
|
delta_y = y - old_y;
|
||||||
|
}
|
||||||
|
old_x = x;
|
||||||
|
old_y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
glm::mat4 createCameraMatrix()
|
||||||
|
{
|
||||||
|
auto rot_y = glm::angleAxis(delta_y * 0.03f, glm::vec3(1, 0, 0));
|
||||||
|
auto rot_x = glm::angleAxis(delta_x * 0.03f, glm::vec3(0, 1, 0));
|
||||||
|
|
||||||
|
dy += delta_y;
|
||||||
|
dx += delta_x;
|
||||||
|
delta_x = 0;
|
||||||
|
delta_y = 0;
|
||||||
|
|
||||||
|
rotation_x = glm::normalize(rot_x * rotation_x);
|
||||||
|
rotation_y = glm::normalize(rot_y * rotation_y);
|
||||||
|
|
||||||
|
rotationCamera = glm::normalize(rotation_y * rotation_x);
|
||||||
|
|
||||||
|
auto inverse_rot = glm::inverse(rotationCamera);
|
||||||
|
|
||||||
|
cameraDir = inverse_rot * glm::vec3(0, 0, -1);
|
||||||
|
glm::vec3 up = glm::vec3(0, 1, 0);
|
||||||
|
cameraSide = inverse_rot * glm::vec3(1, 0, 0);
|
||||||
|
|
||||||
|
glm::mat4 cameraTranslation;
|
||||||
|
cameraTranslation[3] = glm::vec4(-cameraPos, 1.0f);
|
||||||
|
|
||||||
|
return glm::mat4_cast(rotationCamera) * cameraTranslation;
|
||||||
|
}
|
||||||
|
glm::mat4 animationMatrix(float time) {
|
||||||
|
float speed = 1.;
|
||||||
|
time = time * speed;
|
||||||
|
std::vector<float> distances;
|
||||||
|
float timeStep = 0;
|
||||||
|
for (int i = 0; i < keyPoints.size() - 3; i++) {
|
||||||
|
timeStep += (keyPoints[i] - keyPoints[i + 1]).length();
|
||||||
|
distances.push_back((keyPoints[i] - keyPoints[i + 1]).length());
|
||||||
|
}
|
||||||
|
time = fmod(time, timeStep);
|
||||||
|
|
||||||
|
//index of first keyPoint
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
while (distances[index] <= time) {
|
||||||
|
time = time - distances[index];
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//t coefitient between 0 and 1 for interpolation
|
||||||
|
float t = time / distances[index];
|
||||||
|
|
||||||
|
int size = keyPoints.size() - 1;
|
||||||
|
//replace with catmul rom
|
||||||
|
//glm::vec3 pos = (keyPoints[std::max(0, index)] * t + keyPoints[std::min(size, index + 1)] * (1 - t));
|
||||||
|
|
||||||
|
glm::vec3 pos = glm::catmullRom(keyPoints[index], keyPoints[index + 1], keyPoints[index + 2], keyPoints[index + 3], t);
|
||||||
|
|
||||||
|
|
||||||
|
//implement correct animation
|
||||||
|
int keyRotationSize = keyPoints.size() - 1;
|
||||||
|
auto animationRotation = keyRotation[index];
|
||||||
|
//auto animationRotation = glm::slerp(keyRotation[std::max(index, 0)], keyRotation[std::min(keyRotationSize, index)], t);
|
||||||
|
|
||||||
|
glm::mat4 result = glm::translate(pos) * glm::mat4_cast(animationRotation);
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawObject(GLuint program, Core::RenderContext context, glm::mat4 modelMatrix)
|
||||||
|
{
|
||||||
|
glm::mat4 transformation = perspectiveMatrix * cameraMatrix * modelMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(program, "modelMatrix"), 1, GL_FALSE, (float*)&modelMatrix);
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(program, "transformation"), 1, GL_FALSE, (float*)&transformation);
|
||||||
|
context.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderRecursive(std::vector<Core::Node>& nodes) {
|
||||||
|
for (auto node : nodes) {
|
||||||
|
if (node.renderContexts.size() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 transformation = glm::mat4();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// dodaj odwolania do nadrzednych zmiennych
|
||||||
|
for (auto context : node.renderContexts) {
|
||||||
|
auto program = context.material->program;
|
||||||
|
glUseProgram(program);
|
||||||
|
glUniform3f(glGetUniformLocation(program, "cameraPos"), cameraPos.x, cameraPos.y, cameraPos.z);
|
||||||
|
context.material->init_data();
|
||||||
|
drawObject(program, context, transformation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 followCarCamera(float time) {
|
||||||
|
glm::quat rotation_y = glm::normalize(glm::angleAxis(209 * 0.03f, glm::vec3(1, 0, 0)));
|
||||||
|
glm::quat rotation_x = glm::normalize(glm::angleAxis(3.14f, glm::vec3(0, 1, 0)));
|
||||||
|
auto pos = glm::vec3(2, 3, 8);
|
||||||
|
cameraPos = animationMatrix(time) * glm::vec4(pos, 1);
|
||||||
|
auto transformation = animationMatrix(time);
|
||||||
|
glm::vec3 scale;
|
||||||
|
glm::quat rrotation;
|
||||||
|
glm::vec3 translation;
|
||||||
|
glm::vec3 skew;
|
||||||
|
glm::vec4 perspective;
|
||||||
|
glm::decompose(transformation, scale, rrotation, translation, skew, perspective);
|
||||||
|
|
||||||
|
return glm::translate(-pos) * glm::mat4_cast(rotation_y * rotation_x) * glm::inverse(transformation);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderScene(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
// Aktualizacja macierzy widoku i rzutowania. Macierze sa przechowywane w zmiennych globalnych, bo uzywa ich funkcja drawObject.
|
||||||
|
// (Bardziej elegancko byloby przekazac je jako argumenty do funkcji, ale robimy tak dla uproszczenia kodu.
|
||||||
|
// Jest to mozliwe dzieki temu, ze macierze widoku i rzutowania sa takie same dla wszystkich obiektow!)
|
||||||
|
cameraMatrix = createCameraMatrix();
|
||||||
|
perspectiveMatrix = Core::createPerspectiveMatrix(0.1, 2000);
|
||||||
|
float time = glutGet(GLUT_ELAPSED_TIME) / 1000.f;
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glClearColor(0.0f, 0.03f, 0.1f, 1.0f);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (FOLLOW_CAR) {
|
||||||
|
cameraMatrix = followCarCamera(time);
|
||||||
|
}
|
||||||
|
if (!car.empty()) {
|
||||||
|
renderRecursive(city);
|
||||||
|
for (int i = 0; i < 30; i++) {
|
||||||
|
if (time > -10) {
|
||||||
|
car[0].matrix = animationMatrix(time + 15);;
|
||||||
|
renderRecursive(car);
|
||||||
|
time -= 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glUseProgram(0);
|
||||||
|
glfwSwapBuffers(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Core::Material* loadDiffuseMaterial(aiMaterial* material) {
|
||||||
|
aiString colorPath;
|
||||||
|
// use for loading textures
|
||||||
|
|
||||||
|
material->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), colorPath);
|
||||||
|
if (colorPath == aiString("")) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
Core::DiffuseMaterial* result = new Core::DiffuseMaterial();
|
||||||
|
result->texture = Core::LoadTexture(colorPath.C_Str());
|
||||||
|
result->program = programTexture;
|
||||||
|
result->lightDir = lightDir;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Core::Material* loadDiffuseSpecularMaterial(aiMaterial* material) {
|
||||||
|
aiString colorPath;
|
||||||
|
// use for loading textures
|
||||||
|
|
||||||
|
material->Get(AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE, 0), colorPath);
|
||||||
|
Core::DiffuseSpecularMaterial* result = new Core::DiffuseSpecularMaterial();
|
||||||
|
result->texture = Core::LoadTexture(colorPath.C_Str());
|
||||||
|
|
||||||
|
|
||||||
|
aiString specularPath;
|
||||||
|
material->Get(AI_MATKEY_TEXTURE(aiTextureType_SPECULAR, 0), specularPath);
|
||||||
|
result->textureSpecular = Core::LoadTexture(specularPath.C_Str());
|
||||||
|
result->lightDir = lightDir;
|
||||||
|
result->program = programTextureSpecular;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loadRecusive(const aiScene* scene, aiNode* node, std::vector<Core::Node>& nodes, std::vector<Core::Material*> materialsVector, int parentIndex) {
|
||||||
|
int index = nodes.size();
|
||||||
|
nodes.push_back(Core::Node());
|
||||||
|
nodes[index].parent = parentIndex;
|
||||||
|
nodes[index].matrix = Core::mat4_cast(node->mTransformation);
|
||||||
|
for (int i = 0; i < node->mNumMeshes; i++) {
|
||||||
|
Core::RenderContext context;
|
||||||
|
context.initFromAssimpMesh(scene->mMeshes[node->mMeshes[i]]);
|
||||||
|
context.material = materialsVector[scene->mMeshes[node->mMeshes[i]]->mMaterialIndex];
|
||||||
|
nodes[index].renderContexts.push_back(context);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < node->mNumChildren; i++) {
|
||||||
|
loadRecusive(scene, node->mChildren[i], nodes, materialsVector, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void loadRecusive(const aiScene* scene, std::vector<Core::Node>& nodes, std::vector<Core::Material*> materialsVector) {
|
||||||
|
|
||||||
|
loadRecusive(scene, scene->mRootNode, nodes, materialsVector, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initModels() {
|
||||||
|
Assimp::Importer importer;
|
||||||
|
//replace to get more buildings, unrecomdnded
|
||||||
|
//const aiScene* scene = importer.ReadFile("models/blade-runner-style-cityscapes.fbx", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace);
|
||||||
|
const aiScene* scene = importer.ReadFile("models/city_small.fbx", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace);
|
||||||
|
// check for errors
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
|
||||||
|
{
|
||||||
|
std::cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Core::Material*> materialsVector;
|
||||||
|
|
||||||
|
for (int i = 0; i < scene->mNumMaterials; i++) {
|
||||||
|
materialsVector.push_back(loadDiffuseSpecularMaterial(scene->mMaterials[i]));
|
||||||
|
}
|
||||||
|
loadRecusive(scene, city, materialsVector);
|
||||||
|
|
||||||
|
|
||||||
|
scene = importer.ReadFile("models/flying_car.fbx", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace);
|
||||||
|
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) // if is Not Zero
|
||||||
|
{
|
||||||
|
std::cout << "ERROR::ASSIMP:: " << importer.GetErrorString() << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
materialsVector.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < scene->mNumMaterials; i++) {
|
||||||
|
materialsVector.push_back(loadDiffuseMaterial(scene->mMaterials[i]));
|
||||||
|
}
|
||||||
|
loadRecusive(scene, car, materialsVector);
|
||||||
|
|
||||||
|
|
||||||
|
//Recovering points from fbx
|
||||||
|
const aiScene* points = importer.ReadFile("models/path.fbx", aiProcess_Triangulate | aiProcess_GenSmoothNormals | aiProcess_CalcTangentSpace);
|
||||||
|
|
||||||
|
auto root = points->mRootNode;
|
||||||
|
|
||||||
|
for (int i = 0; i < root->mNumChildren; i++) {
|
||||||
|
auto node = root->mChildren[i];
|
||||||
|
//std::cout << "glm::vec3(" << node->mTransformation.a4 << "f, " << node->mTransformation.b4 << "f, " << node->mTransformation.c4 << "f), " << std::endl;
|
||||||
|
//std::cout << node->mName.C_Str() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void initKeyRotation() {
|
||||||
|
glm::vec3 oldDirection = glm::vec3(0.0f, 0.0f, 1.0f);
|
||||||
|
glm::quat oldRotationCamera = glm::quat(1, 0, 0, 0);
|
||||||
|
glm::vec3 direction;
|
||||||
|
glm::quat rotation;
|
||||||
|
for (int i = 0; i < keyPoints.size() - 1; i++) {
|
||||||
|
//3.1
|
||||||
|
direction = glm::normalize(keyPoints[i + 1] - keyPoints[i]);
|
||||||
|
//3.2
|
||||||
|
// oldDirection/direction
|
||||||
|
rotation = glm::normalize(glm::rotation(oldDirection, direction) * oldRotationCamera);
|
||||||
|
//3.3
|
||||||
|
keyRotation.push_back(rotation);
|
||||||
|
//3.4
|
||||||
|
oldDirection = direction;
|
||||||
|
oldRotationCamera = rotation;
|
||||||
|
//std::cout << direction.x << " " << direction.y << " " << direction.z << " " << std::endl;
|
||||||
|
//std::cout << keyPoints[i].x << " " << keyPoints[i].y << " " << keyPoints[i].z << " " << std::endl;
|
||||||
|
//std::cout << rotation.x << " " << rotation.y << " " << rotation.z << " " << rotation.w << std::endl << std::endl;
|
||||||
|
}
|
||||||
|
keyRotation.push_back(glm::quat(1, 0, 0, 0));
|
||||||
|
//for (auto rot : keyRotation) {
|
||||||
|
// std::cout << rot.x << " " << rot.y << " " << rot.z << " " << rot.w << std::endl;
|
||||||
|
//}
|
||||||
|
//std::cout << std::endl << keyRotation.size() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
|
||||||
|
{
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(GLFWwindow* window){
|
||||||
|
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
program = shaderLoader.CreateProgram("shaders/shader_4_1.vert", "shaders/shader_4_1.frag");
|
||||||
|
programTextureSpecular = shaderLoader.CreateProgram("shaders/shader_spec_tex.vert", "shaders/shader_spec_tex.frag");
|
||||||
|
programTexture = shaderLoader.CreateProgram("shaders/shader_tex_2.vert", "shaders/shader_tex_2.frag");
|
||||||
|
programSun = shaderLoader.CreateProgram("shaders/shader_4_sun.vert", "shaders/shader_4_sun.frag");
|
||||||
|
|
||||||
|
initModels();
|
||||||
|
|
||||||
|
initKeyRotation();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void shutdown(GLFWwindow* window)
|
||||||
|
{
|
||||||
|
shaderLoader.DeleteProgram(program);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// funkcja jest glowna petla
|
||||||
|
void renderLoop(GLFWwindow* window) {
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
|
processInput(window);
|
||||||
|
|
||||||
|
renderScene(window);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
}
|
47
cw 11/src/main.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#include "glew.h"
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include "glm.hpp"
|
||||||
|
#include "ext.hpp"
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "ex_10_1.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
// inicjalizacja 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
|
||||||
|
|
||||||
|
// tworzenie okna za pomoca glfw
|
||||||
|
GLFWwindow* window = glfwCreateWindow(500, 500, "FirstWindow", NULL, NULL);
|
||||||
|
if (window == NULL)
|
||||||
|
{
|
||||||
|
std::cout << "Failed to create GLFW window" << std::endl;
|
||||||
|
glfwTerminate();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
glfwMakeContextCurrent(window);
|
||||||
|
|
||||||
|
// ladowanie OpenGL za pomoca glew
|
||||||
|
glewInit();
|
||||||
|
glViewport(0, 0, 500, 500);
|
||||||
|
|
||||||
|
init(window);
|
||||||
|
|
||||||
|
// uruchomienie glownej petli
|
||||||
|
renderLoop(window);
|
||||||
|
|
||||||
|
shutdown(window);
|
||||||
|
glfwTerminate();
|
||||||
|
return 0;
|
||||||
|
}
|
291
cw 11/src/objload.h
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/* Copyright (c) 2012, Gerhard Reitmayr
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||||||
|
|
||||||
|
#ifndef OBJLOAD_H_
|
||||||
|
#define OBJLOAD_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace obj {
|
||||||
|
|
||||||
|
struct Model {
|
||||||
|
std::vector<float> vertex; //< 3 * N entries
|
||||||
|
std::vector<float> texCoord; //< 2 * N entries
|
||||||
|
std::vector<float> normal; //< 3 * N entries
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<unsigned short> > faces; //< assume triangels and uniform indexing
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ObjModel {
|
||||||
|
struct FaceVertex {
|
||||||
|
FaceVertex() : v(-1), t(-1), n(-1) {}
|
||||||
|
int v, t, n;
|
||||||
|
|
||||||
|
bool operator<( const FaceVertex & other ) const;
|
||||||
|
bool operator==( const FaceVertex & other ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::pair<std::vector<FaceVertex>, std::vector<unsigned> > FaceList;
|
||||||
|
|
||||||
|
std::vector<float> vertex; //< 3 * N entries
|
||||||
|
std::vector<float> texCoord; //< 2 * N entries
|
||||||
|
std::vector<float> normal; //< 3 * N entries
|
||||||
|
|
||||||
|
std::map<std::string, FaceList > faces;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ObjModel parseObjModel( std::istream & in);
|
||||||
|
inline void tesselateObjModel( ObjModel & obj);
|
||||||
|
inline ObjModel tesselateObjModel( const ObjModel & obj );
|
||||||
|
inline Model convertToModel( const ObjModel & obj );
|
||||||
|
|
||||||
|
inline Model loadModel( std::istream & in );
|
||||||
|
inline Model loadModelFromString( const std::string & in );
|
||||||
|
inline Model loadModelFromFile( const std::string & in );
|
||||||
|
|
||||||
|
inline std::ostream & operator<<( std::ostream & out, const Model & m );
|
||||||
|
inline std::ostream & operator<<( std::ostream & out, const ObjModel::FaceVertex & f);
|
||||||
|
|
||||||
|
// ---------------------------- Implementation starts here -----------------------
|
||||||
|
|
||||||
|
inline bool ObjModel::FaceVertex::operator<( const ObjModel::FaceVertex & other ) const {
|
||||||
|
return (v < other.v) || (v == other.v && t < other.t ) || (v == other.v && t == other.t && n < other.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool ObjModel::FaceVertex::operator==( const ObjModel::FaceVertex & other ) const {
|
||||||
|
return (v == other.v && t == other.t && n == other.n);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::istream & operator>>(std::istream & in, std::vector<T> & vec ){
|
||||||
|
T temp;
|
||||||
|
if(in >> temp)
|
||||||
|
vec.push_back(temp);
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline std::istream & operator>>(std::istream & in, std::set<T> & vec ){
|
||||||
|
T temp;
|
||||||
|
if(in >> temp)
|
||||||
|
vec.insert(temp);
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::istream & operator>>( std::istream & in, ObjModel::FaceVertex & f){
|
||||||
|
if(in >> f.v){
|
||||||
|
if(in.peek() == '/'){
|
||||||
|
in.get();
|
||||||
|
in >> f.t;
|
||||||
|
in.clear();
|
||||||
|
if(in.peek() == '/'){
|
||||||
|
in.get();
|
||||||
|
in >> f.n;
|
||||||
|
in.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.clear();
|
||||||
|
--f.v;
|
||||||
|
--f.t;
|
||||||
|
--f.n;
|
||||||
|
}
|
||||||
|
// std::cout << f << std::endl;
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjModel parseObjModel( std::istream & in ){
|
||||||
|
char line[1024];
|
||||||
|
std::string op;
|
||||||
|
std::istringstream line_in;
|
||||||
|
std::set<std::string> groups;
|
||||||
|
groups.insert("default");
|
||||||
|
|
||||||
|
ObjModel data;
|
||||||
|
|
||||||
|
while(in.good()){
|
||||||
|
in.getline(line, 1023);
|
||||||
|
line_in.clear();
|
||||||
|
line_in.str(line);
|
||||||
|
|
||||||
|
if(!(line_in >> op))
|
||||||
|
continue;
|
||||||
|
if(op == "v")
|
||||||
|
line_in >> data.vertex >> data.vertex >> data.vertex;
|
||||||
|
else if(op == "vt")
|
||||||
|
line_in >> data.texCoord >> data.texCoord >> data.texCoord;
|
||||||
|
else if(op == "vn")
|
||||||
|
line_in >> data.normal >> data.normal >> data.normal;
|
||||||
|
else if(op == "g"){
|
||||||
|
groups.clear();
|
||||||
|
while(line_in >> groups) ;
|
||||||
|
groups.insert("default");
|
||||||
|
}
|
||||||
|
else if(op == "f") {
|
||||||
|
std::vector<ObjModel::FaceVertex> list;
|
||||||
|
while(line_in >> list) ;
|
||||||
|
|
||||||
|
for(std::set<std::string>::const_iterator g = groups.begin(); g != groups.end(); ++g){
|
||||||
|
ObjModel::FaceList & fl = data.faces[*g];
|
||||||
|
fl.second.push_back(fl.first.size());
|
||||||
|
fl.first.insert(fl.first.end(), list.begin(), list.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(std::map<std::string, ObjModel::FaceList>::iterator g = data.faces.begin(); g != data.faces.end(); ++g){
|
||||||
|
ObjModel::FaceList & fl = g->second;
|
||||||
|
fl.second.push_back(fl.first.size());
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void tesselateObjModel( std::vector<ObjModel::FaceVertex> & input, std::vector<unsigned> & input_start){
|
||||||
|
std::vector<ObjModel::FaceVertex> output;
|
||||||
|
std::vector<unsigned> output_start;
|
||||||
|
output.reserve(input.size());
|
||||||
|
output_start.reserve(input_start.size());
|
||||||
|
|
||||||
|
for(std::vector<unsigned>::const_iterator s = input_start.begin(); s != input_start.end() - 1; ++s){
|
||||||
|
const unsigned size = *(s+1) - *s;
|
||||||
|
if(size > 3){
|
||||||
|
const ObjModel::FaceVertex & start_vertex = input[*s];
|
||||||
|
for( int i = 1; i < (int)size-1; ++i){
|
||||||
|
output_start.push_back(output.size());
|
||||||
|
output.push_back(start_vertex);
|
||||||
|
output.push_back(input[*s+i]);
|
||||||
|
output.push_back(input[*s+i+1]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output_start.push_back(output.size());
|
||||||
|
output.insert(output.end(), input.begin() + *s, input.begin() + *(s+1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output_start.push_back(output.size());
|
||||||
|
input.swap(output);
|
||||||
|
input_start.swap(output_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tesselateObjModel( ObjModel & obj){
|
||||||
|
for(std::map<std::string, ObjModel::FaceList>::iterator g = obj.faces.begin(); g != obj.faces.end(); ++g){
|
||||||
|
ObjModel::FaceList & fl = g->second;
|
||||||
|
tesselateObjModel(fl.first, fl.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Model convertToModel( const ObjModel & obj ) {
|
||||||
|
// insert all face vertices into a vector and make unique
|
||||||
|
std::vector<ObjModel::FaceVertex> unique(obj.faces.find("default")->second.first);
|
||||||
|
std::sort(unique.begin(), unique.end());
|
||||||
|
unique.erase( std::unique(unique.begin(), unique.end()), unique.end());
|
||||||
|
|
||||||
|
// build a new model with repeated vertices/texcoords/normals to have single indexing
|
||||||
|
Model model;
|
||||||
|
for(std::vector<ObjModel::FaceVertex>::const_iterator f = unique.begin(); f != unique.end(); ++f){
|
||||||
|
model.vertex.insert(model.vertex.end(), obj.vertex.begin() + 3*f->v, obj.vertex.begin() + 3*f->v + 3);
|
||||||
|
if(!obj.texCoord.empty()){
|
||||||
|
const int index = (f->t > -1) ? f->t : f->v;
|
||||||
|
model.texCoord.insert(model.texCoord.end(), obj.texCoord.begin() + 2*index, obj.texCoord.begin() + 2*index + 2);
|
||||||
|
}
|
||||||
|
if(!obj.normal.empty()){
|
||||||
|
const int index = (f->n > -1) ? f->n : f->v;
|
||||||
|
model.normal.insert(model.normal.end(), obj.normal.begin() + 3*index, obj.normal.begin() + 3*index + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// look up unique index and transform face descriptions
|
||||||
|
for(std::map<std::string, ObjModel::FaceList>::const_iterator g = obj.faces.begin(); g != obj.faces.end(); ++g){
|
||||||
|
const std::string & name = g->first;
|
||||||
|
const ObjModel::FaceList & fl = g->second;
|
||||||
|
std::vector<unsigned short> & v = model.faces[g->first];
|
||||||
|
v.reserve(fl.first.size());
|
||||||
|
for(std::vector<ObjModel::FaceVertex>::const_iterator f = fl.first.begin(); f != fl.first.end(); ++f){
|
||||||
|
const unsigned short index = std::distance(unique.begin(), std::lower_bound(unique.begin(), unique.end(), *f));
|
||||||
|
v.push_back(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjModel tesselateObjModel( const ObjModel & obj ){
|
||||||
|
ObjModel result = obj;
|
||||||
|
tesselateObjModel(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Model loadModel( std::istream & in ){
|
||||||
|
ObjModel model = parseObjModel(in);
|
||||||
|
tesselateObjModel(model);
|
||||||
|
return convertToModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
Model loadModelFromString( const std::string & str ){
|
||||||
|
std::istringstream in(str);
|
||||||
|
return loadModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Model loadModelFromFile( const std::string & str) {
|
||||||
|
std::ifstream in(str.c_str());
|
||||||
|
return loadModel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream & operator<<( std::ostream & out, const ObjModel::FaceVertex & f){
|
||||||
|
out << f.v << "\t" << f.t << "\t" << f.n;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream & operator<<( std::ostream & out, const Model & m ){
|
||||||
|
if(!m.vertex.empty()){
|
||||||
|
out << "vertex\n";
|
||||||
|
for(int i = 0; i < (int)m.vertex.size(); ++i)
|
||||||
|
out << m.vertex[i] << (((i % 3) == 2)?"\n":"\t");
|
||||||
|
}
|
||||||
|
if(!m.texCoord.empty()){
|
||||||
|
out << "texCoord\n";
|
||||||
|
for(int i = 0; i < (int)m.texCoord.size(); ++i)
|
||||||
|
out << m.texCoord[i] << (((i % 2) == 1)?"\n":"\t");
|
||||||
|
}
|
||||||
|
if(!m.normal.empty()){
|
||||||
|
out << "normal\n";
|
||||||
|
for(int i = 0; i < (int)m.normal.size(); ++i)
|
||||||
|
out << m.normal[i] << (((i % 3) == 2)?"\n":"\t");
|
||||||
|
}
|
||||||
|
if(!m.faces.empty()){
|
||||||
|
out << "faces\t";
|
||||||
|
for(std::map<std::string, std::vector<unsigned short> >::const_iterator g = m.faces.begin(); g != m.faces.end(); ++g){
|
||||||
|
out << g->first << " ";
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
|
// for(int i = 0; i < m.face.size(); ++i)
|
||||||
|
// out << m.face[i] << (((i % 3) == 2)?"\n":"\t");
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace obj
|
||||||
|
|
||||||
|
#endif // OBJLOAD_H_
|
107
cw 11/style.css
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||||
|
|
||||||
|
body{
|
||||||
|
color:#444;
|
||||||
|
font-family:Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif;
|
||||||
|
font-size:12px;
|
||||||
|
line-height:1.5em;
|
||||||
|
padding:1em;
|
||||||
|
margin:auto;
|
||||||
|
max-width:42em;
|
||||||
|
background:#fefefe;
|
||||||
|
}
|
||||||
|
|
||||||
|
a{ color: #0645ad; text-decoration:none;}
|
||||||
|
a:visited{ color: #0b0080; }
|
||||||
|
a:hover{ color: #06e; }
|
||||||
|
a:active{ color:#faa700; }
|
||||||
|
a:focus{ outline: thin dotted; }
|
||||||
|
a:hover, a:active{ outline: 0; }
|
||||||
|
|
||||||
|
::-moz-selection{background:rgba(255,255,0,0.3);color:#000}
|
||||||
|
::selection{background:rgba(255,255,0,0.3);color:#000}
|
||||||
|
|
||||||
|
a::-moz-selection{background:rgba(255,255,0,0.3);color:#0645ad}
|
||||||
|
a::selection{background:rgba(255,255,0,0.3);color:#0645ad}
|
||||||
|
|
||||||
|
p{
|
||||||
|
margin:1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
img{
|
||||||
|
max-width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6{
|
||||||
|
font-weight:normal;
|
||||||
|
color:#111;
|
||||||
|
line-height:1em;
|
||||||
|
}
|
||||||
|
h4,h5,h6{ font-weight: bold; }
|
||||||
|
h1{ font-size:2.5em; }
|
||||||
|
h2{ font-size:2em; }
|
||||||
|
h3{ font-size:1.5em; }
|
||||||
|
h4{ font-size:1.2em; }
|
||||||
|
h5{ font-size:1em; }
|
||||||
|
h6{ font-size:0.9em; }
|
||||||
|
|
||||||
|
blockquote{
|
||||||
|
color:#666666;
|
||||||
|
margin:0;
|
||||||
|
padding-left: 3em;
|
||||||
|
border-left: 0.5em #EEE solid;
|
||||||
|
}
|
||||||
|
hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa;border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; }
|
||||||
|
pre, code, kbd, samp { color: #000; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; }
|
||||||
|
pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
|
||||||
|
|
||||||
|
b, strong { font-weight: bold; }
|
||||||
|
|
||||||
|
dfn { font-style: italic; }
|
||||||
|
|
||||||
|
ins { background: #ff9; color: #000; text-decoration: none; }
|
||||||
|
|
||||||
|
mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
|
||||||
|
|
||||||
|
sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
|
||||||
|
sup { top: -0.5em; }
|
||||||
|
sub { bottom: -0.25em; }
|
||||||
|
|
||||||
|
ul, ol { margin: 1em 0; padding: 0 0 0 2em; }
|
||||||
|
li p:last-child { margin:0 }
|
||||||
|
dd { margin: 0 0 0 2em; }
|
||||||
|
|
||||||
|
img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
th { border-bottom: 1px solid black; }
|
||||||
|
td { vertical-align: top; }
|
||||||
|
|
||||||
|
@media only screen and (min-width: 480px) {
|
||||||
|
body{font-size:14px;}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 768px) {
|
||||||
|
body{font-size:16px;}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
* { background: transparent !important; color: black !important; filter:none !important; -ms-filter: none !important; }
|
||||||
|
body{font-size:12pt; max-width:100%;}
|
||||||
|
a, a:visited { text-decoration: underline; }
|
||||||
|
hr { height: 1px; border:0; border-bottom:1px solid black; }
|
||||||
|
a[href]:after { content: " (" attr(href) ")"; }
|
||||||
|
abbr[title]:after { content: " (" attr(title) ")"; }
|
||||||
|
.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }
|
||||||
|
pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; }
|
||||||
|
tr, img { page-break-inside: avoid; }
|
||||||
|
img { max-width: 100% !important; }
|
||||||
|
@page :left { margin: 15mm 20mm 15mm 10mm; }
|
||||||
|
@page :right { margin: 15mm 10mm 15mm 20mm; }
|
||||||
|
p, h2, h3 { orphans: 3; widows: 3; }
|
||||||
|
h2, h3 { page-break-after: avoid; }
|
||||||
|
}
|
BIN
cw 11/textures/B1.png
Normal file
After Width: | Height: | Size: 4.1 MiB |
BIN
cw 11/textures/B1R.png
Normal file
After Width: | Height: | Size: 2.6 MiB |
BIN
cw 11/textures/B2.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
cw 11/textures/B2R.png
Normal file
After Width: | Height: | Size: 2.6 MiB |