Merge pull request #1 from KrakenEngine/feature-vulkan

Feature vulkan merged to master.  Work to continue there
This commit is contained in:
2019-12-08 16:36:31 -08:00
committed by GitHub
605 changed files with 15797 additions and 43117 deletions

3
.gitmodules vendored
View File

@@ -7,3 +7,6 @@
[submodule "hydra"] [submodule "hydra"]
path = hydra path = hydra
url = git@github.com:KrakenEngine/hydra.git url = git@github.com:KrakenEngine/hydra.git
[submodule "3rdparty/glslang"]
path = 3rdparty/glslang
url = git@github.com:KhronosGroup/glslang.git

View File

@@ -1,4 +0,0 @@
syntax: glob
kraken_win\kraken.VC.db
kraken_win/build/
build/

View File

@@ -1 +0,0 @@
be35d62159788e03c335f8b7f3ddbde8030a3ccf Release 1.0.2

View File

@@ -3,7 +3,7 @@ compiler: clang
branches: branches:
only: only:
- master - feature-vulkan
matrix: matrix:
include: include:
@@ -14,7 +14,6 @@ matrix:
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
packages: packages:
- libc++-dev - libc++-dev
- libboost-dev
- os: osx - os: osx
osx_image: xcode9.1 osx_image: xcode9.1

1
3rdparty/glslang vendored Submodule

Submodule 3rdparty/glslang added at 83af469512

View File

@@ -1,9 +1,17 @@
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.8)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if (NOT WIN32) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
else(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
# Likely MSVC...
# Build with more cores
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
if (NOT WIN32 AND NOT ANDROID)
set(CMAKE_CXX_COMPILER "clang++") set(CMAKE_CXX_COMPILER "clang++")
endif() endif()
@@ -27,6 +35,21 @@ macro (add_sources)
endif() endif()
endmacro() endmacro()
macro (add_standard_asset)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN})
if (_relPath)
list (APPEND KRAKEN_STANDARD_ASSETS "${_relPath}/${_src}")
else()
list (APPEND KRAKEN_STANDARD_ASSETS "${_src}")
endif()
endforeach()
if (_relPath)
# propagate KRAKEN_STANDARD_ASSETS to parent directory
set (KRAKEN_STANDARD_ASSETS ${KRAKEN_STANDARD_ASSETS} PARENT_SCOPE)
endif()
endmacro()
macro (add_public_header) macro (add_public_header)
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}") file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
foreach (_src ${ARGN}) foreach (_src ${ARGN})
@@ -43,6 +66,8 @@ macro (add_public_header)
endmacro() endmacro()
IF(APPLE) IF(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated -Wno-deprecated-declarations -Wno-c++11-extensions")
# SET(GUI_TYPE MACOSX_BUNDLE) # SET(GUI_TYPE MACOSX_BUNDLE)
# INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon ) # INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon )
FIND_LIBRARY(APPKIT_LIBRARY AppKit) FIND_LIBRARY(APPKIT_LIBRARY AppKit)
@@ -73,70 +98,123 @@ add_public_header(hydra/include/vector3.h)
add_public_header(hydra/include/vector4.h) add_public_header(hydra/include/vector4.h)
add_public_header(hydra/include/vector2i.h) add_public_header(hydra/include/vector2i.h)
add_library(kraken SHARED ${SRCS} ${KRAKEN_PUBLIC_HEADERS}) # ---- Android ----
if(ANDROID)
set(Boost_USE_STATIC_LIBS ON) # only find static libs add_subdirectory(kraken_android)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost 1.54.0)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(kraken ${Boost_LIBRARIES})
endif() endif()
# ---- Hydra ---- # ---- Hydra ----
add_subdirectory(hydra) add_subdirectory(hydra)
include_directories(hydra/include) include_directories(hydra/include)
target_link_libraries(kraken hydra) list (APPEND EXTRA_LIBS hydra)
# ---- Vulkan ----
if(NOT ANDROID)
find_package(Vulkan REQUIRED)
list (APPEND EXTRA_LIBS Vulkan::Vulkan)
endif()
# ---- GLSlang ----
if(NOT ANDROID)
set(ENABLE_GLSLANG_BINARIES OFF)
set(ENABLE_GLSLANG_INSTALL OFF)
set(ENABLE_SPVREMAPPER OFF)
add_subdirectory(3rdparty/glslang)
include_directories(3rdparty/glslang/Public)
list (APPEND EXTRA_LIBS "glslang")
list (APPEND EXTRA_LIBS "SPIRV")
endif()
# ---- OpenGL ---- # ---- OpenGL ----
if(ANDROID)
list (APPEND EXTRA_LIBS "EGL")
list (APPEND EXTRA_LIBS "GLESv3")
else()
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
include_directories( ${OPENGL_INCLUDE_DIRS} ) include_directories( ${OPENGL_INCLUDE_DIRS} )
target_link_libraries(kraken ${OPENGL_LIBRARIES}) list (APPEND EXTRA_LIBS "${OPENGL_LIBRARIES}")
endif()
# ---- GLAD ---- # ---- GLAD ----
if(NOT ANDROID)
set(GLAD_EXTENSIONS "GL_EXT_texture_filter_anisotropic,GL_EXT_texture_compression_s3tc, GL_S3_s3tc" CACHE STRING "Gl exts" FORCE) set(GLAD_EXTENSIONS "GL_EXT_texture_filter_anisotropic,GL_EXT_texture_compression_s3tc, GL_S3_s3tc" CACHE STRING "Gl exts" FORCE)
add_subdirectory(3rdparty/glad) add_subdirectory(3rdparty/glad)
include_directories(${GLAD_INCLUDE_DIRS}) include_directories(${GLAD_INCLUDE_DIRS})
target_link_libraries(kraken glad) list (APPEND EXTRA_LIBS "glad")
endif()
# ---- GLFW ---- # ---- GLFW ----
if(NOT ANDROID)
set(GLFW_BUILD_EXAMPLES OFF CACHE INTERNAL "Build the GLFW example programs") set(GLFW_BUILD_EXAMPLES OFF CACHE INTERNAL "Build the GLFW example programs")
set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "Build the GLFW test programs") set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "Build the GLFW test programs")
set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "Build the GLFW documentation") set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "Build the GLFW documentation")
set(GLFW_INSTALL OFF CACHE INTERNAL "Generate installation target") set(GLFW_INSTALL OFF CACHE INTERNAL "Generate installation target")
add_subdirectory(3rdparty/glfw) add_subdirectory(3rdparty/glfw)
include_directories(3rdparty/glfw/include) include_directories(3rdparty/glfw/include)
target_link_libraries(kraken glfw ${GLFW_LIBRARIES}) list (APPEND EXTRA_LIBS "${GLFW_LIBRARIES}")
endif()
add_custom_command(
OUTPUT ${KRAKEN_PUBLIC_HEADERS_OUTPUT}
// COMMAND kraken_convert -o ${STANDARD_ASSET_BUNDLE} ${KRAKEN_STANDARD_ASSETS}
// DEPENDS kraken_convert ${KRAKEN_STANDARD_ASSETS}
COMMENT "Copying public headers"
)
add_library(kraken STATIC ${SRCS} ${KRAKEN_PUBLIC_HEADERS} ${KRAKEN_PUBLIC_HEADERS_OUTPUT})
TARGET_LINK_LIBRARIES( kraken ${EXTRA_LIBS} ) TARGET_LINK_LIBRARIES( kraken ${EXTRA_LIBS} )
SET_TARGET_PROPERTIES( SET_TARGET_PROPERTIES(
kraken kraken
PROPERTIES PROPERTIES
FRAMEWORK ON
SOVERSION 0
VERSION 0.1.0
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}" PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
PRIVATE_HEADER "${PRIVATE_HEADER_FILES}" PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
ARCHIVE_OUTPUT_DIRECTORY "archive" ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
LIBRARY_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
OUTPUT_NAME kraken OUTPUT_NAME kraken
) )
# install(TARGETS kraken DESTINATION ${PROJECT_BINARY_DIR}/lib${LIB_SUFFIX})
# install(FILES ${KRAKEN_PUBLIC_HEADERS} DESTINATION ${PROJECT_BINARY_DIR}/include)
# INSTALL(TARGETS kraken
# LIBRARY DESTINATION "lib${LIB_SUFFIX}"
# ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
# PUBLIC_HEADER DESTINATION "include"
# )
# add_custom_target(package # add_custom_target(package
# COMMENT "Compressing..." # COMMENT "Compressing..."
# WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/archive" # WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/archive"
# COMMAND ${CMAKE_COMMAND} -E tar "cfvz" "kraken.tgz" "*" # COMMAND ${CMAKE_COMMAND} -E tar "cfvz" "kraken.tgz" "*"
# ) # )
install(TARGETS kraken
RUNTIME DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/bin/win
PUBLIC_HEADER DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/include
ARCHIVE DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
LIBRARY DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/${CMAKE_BUILD_TYPE}/lib/win
)
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
install (FILES $<TARGET_PDB_FILE:kraken>
DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/export/lib/win)
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)
set(KRAKEN_PUBLIC_HEADERS_OUTPUT ${KRAKEN_PUBLIC_HEADERS})
list(TRANSFORM KRAKEN_PUBLIC_HEADERS_OUTPUT PREPEND "${CMAKE_BINARY_DIR}/output/include")
add_subdirectory(standard_assets)
SET(STANDARD_ASSET_BUNDLE "${CMAKE_BINARY_DIR}/output/assets/standard_assets.krbundle")
add_custom_command(
OUTPUT ${STANDARD_ASSET_BUNDLE}
COMMAND kraken_convert -o ${STANDARD_ASSET_BUNDLE} ${KRAKEN_STANDARD_ASSETS}
DEPENDS kraken_convert ${KRAKEN_STANDARD_ASSETS}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Creating Standard Assets"
)
add_custom_target(standard_assets ALL
DEPENDS ${STANDARD_ASSET_BUNDLE}
VERBATIM
)
add_subdirectory(tests)
add_subdirectory(tools)
set_target_properties( kraken PROPERTIES
RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/output/lib
RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/output/lib
)

41
CMakeSettings.json Normal file
View File

@@ -0,0 +1,41 @@
{
// See https://go.microsoft.com//fwlink//?linkid=834763 for more information about this file.
"configurations": [
{
"name": "x86-Debug",
"generator": "Visual Studio 15 2017",
"configurationType" : "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"ctestCommandArgs": ""
},
{
"name": "x86-Release",
"generator": "Visual Studio 15 2017",
"configurationType" : "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"ctestCommandArgs": ""
},
{
"name": "x64-Debug",
"generator": "Visual Studio 15 2017 Win64",
"configurationType" : "Debug",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"ctestCommandArgs": ""
},
{
"name": "x64-Release",
"generator": "Visual Studio 15 2017 Win64",
"configurationType" : "Release",
"buildRoot": "${env.LOCALAPPDATA}\\CMakeBuild\\${workspaceHash}\\build\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "-m -v:minimal",
"ctestCommandArgs": ""
}
]
}

1
configure_macos.sh Executable file
View File

@@ -0,0 +1 @@
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-apple-darwin-clang.cmake"

2
configure_win64.bat Normal file
View File

@@ -0,0 +1,2 @@
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
cmake -H. -G Ninja -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"

2
configure_win64_msvc.bat Normal file
View File

@@ -0,0 +1,2 @@
rem call "%VSINSTALLDIR%VC\Auxiliary\Build\vcvars64.bat"
cmake -H. -G"Visual Studio 16 2019" -Bbuild -DCMAKE_TOOLCHAIN_FILE="toolchain/toolchain-x86_64-pc-windows-msvc.cmake"

2
hydra

Submodule hydra updated: 5cca3a9fb1...dff00680fa

View File

@@ -3,6 +3,7 @@ add_subdirectory(public)
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE) set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
# Private Implementation # Private Implementation
add_sources(kraken.cpp)
add_sources(KRAmbientZone.cpp) add_sources(KRAmbientZone.cpp)
add_sources(KRAnimation.cpp) add_sources(KRAnimation.cpp)
add_sources(KRAnimationAttribute.cpp) add_sources(KRAnimationAttribute.cpp)
@@ -63,11 +64,16 @@ add_sources(KRResource+blend.cpp)
# add_sources(KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies # add_sources(KRResource+fbx.cpp) # TODO - Locate FBX SDK dependencies
add_sources(KRResource+obj.cpp) add_sources(KRResource+obj.cpp)
add_sources(KRResource.cpp) add_sources(KRResource.cpp)
add_sources(KRResourceManager.cpp)
add_sources(KRReverbZone.cpp) add_sources(KRReverbZone.cpp)
add_sources(KRScene.cpp) add_sources(KRScene.cpp)
add_sources(KRSceneManager.cpp) add_sources(KRSceneManager.cpp)
add_sources(KRShader.cpp) add_sources(KRShader.cpp)
add_sources(KRShaderManager.cpp) add_sources(KRShaderManager.cpp)
add_sources(KRSource.cpp)
add_sources(KRSourceManager.cpp)
add_sources(KRPipeline.cpp)
add_sources(KRPipelineManager.cpp)
add_sources(KRSpotLight.cpp) add_sources(KRSpotLight.cpp)
add_sources(KRSprite.cpp) add_sources(KRSprite.cpp)
add_sources(KRTexture.cpp) add_sources(KRTexture.cpp)

View File

@@ -1,167 +1,167 @@
// //
// KRAmbientZone.cpp // KRAmbientZone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRAmbientZone.h" #include "KRAmbientZone.h"
#include "KRContext.h" #include "KRContext.h"
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name) KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_ambient = ""; m_ambient = "";
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
KRAmbientZone::~KRAmbientZone() KRAmbientZone::~KRAmbientZone()
{ {
} }
std::string KRAmbientZone::getElementName() { std::string KRAmbientZone::getElementName() {
return "ambient_zone"; return "ambient_zone";
} }
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str()); e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_ambient.c_str()); e->SetAttribute("sample", m_ambient.c_str());
e->SetAttribute("gain", m_ambient_gain); e->SetAttribute("gain", m_ambient_gain);
e->SetAttribute("gradient", m_gradient_distance); e->SetAttribute("gradient", m_gradient_distance);
return e; return e;
} }
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e) void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_zone = e->Attribute("zone"); m_zone = e->Attribute("zone");
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
m_ambient = e->Attribute("sample"); m_ambient = e->Attribute("sample");
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
m_ambient_gain = 1.0f; m_ambient_gain = 1.0f;
} }
} }
std::string KRAmbientZone::getAmbient() std::string KRAmbientZone::getAmbient()
{ {
return m_ambient; return m_ambient;
} }
void KRAmbientZone::setAmbient(const std::string &ambient) void KRAmbientZone::setAmbient(const std::string &ambient)
{ {
m_ambient = ambient; m_ambient = ambient;
} }
float KRAmbientZone::getAmbientGain() float KRAmbientZone::getAmbientGain()
{ {
return m_ambient_gain; return m_ambient_gain;
} }
void KRAmbientZone::setAmbientGain(float ambient_gain) void KRAmbientZone::setAmbientGain(float ambient_gain)
{ {
m_ambient_gain = ambient_gain; m_ambient_gain = ambient_gain;
} }
std::string KRAmbientZone::getZone() std::string KRAmbientZone::getZone()
{ {
return m_zone; return m_zone;
} }
void KRAmbientZone::setZone(const std::string &zone) void KRAmbientZone::setZone(const std::string &zone)
{ {
m_zone = zone; m_zone = zone;
} }
void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRAmbientZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pPipeline = getContext().getPipelineManager()->getPipeline("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pPipeline, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
float KRAmbientZone::getGradientDistance() float KRAmbientZone::getGradientDistance()
{ {
return m_gradient_distance; return m_gradient_distance;
} }
void KRAmbientZone::setGradientDistance(float gradient_distance) void KRAmbientZone::setGradientDistance(float gradient_distance)
{ {
m_gradient_distance = gradient_distance; m_gradient_distance = gradient_distance;
} }
AABB KRAmbientZone::getBounds() { AABB KRAmbientZone::getBounds() {
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box // Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
float KRAmbientZone::getContainment(const Vector3 &pos) float KRAmbientZone::getContainment(const Vector3 &pos)
{ {
AABB bounds = getBounds(); AABB bounds = getBounds();
if(bounds.contains(pos)) { if(bounds.contains(pos)) {
Vector3 size = bounds.size(); Vector3 size = bounds.size();
Vector3 diff = pos - bounds.center(); Vector3 diff = pos - bounds.center();
diff = diff * 2.0f; diff = diff * 2.0f;
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z); diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
float d = diff.magnitude(); float d = diff.magnitude();
if(m_gradient_distance <= 0.0f) { if(m_gradient_distance <= 0.0f) {
// Avoid division by zero // Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f; d = d > 1.0f ? 0.0f : 1.0f;
} else { } else {
d = (1.0f - d) / m_gradient_distance; d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f); d = KRCLAMP(d, 0.0f, 1.0f);
} }
return d; return d;
} else { } else {
return 0.0f; return 0.0f;
} }
} }

View File

@@ -28,8 +28,6 @@
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include "KRAnimation.h" #include "KRAnimation.h"
#include "KRAnimationManager.h" #include "KRAnimationManager.h"
#include "KRContext.h" #include "KRContext.h"
@@ -291,7 +289,7 @@ KRAnimation *KRAnimation::split(const std::string &name, float start_time, float
KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext()); KRAnimationAttribute *new_attribute = new KRAnimationAttribute(getContext());
KRAnimationCurve *new_curve = curve; KRAnimationCurve *new_curve = curve;
if(clone_curves) { if(clone_curves) {
std::string new_curve_name = name + "_curve" + boost::lexical_cast<std::string>(++new_curve_count); std::string new_curve_name = name + "_curve" + std::to_string(++new_curve_count);
new_curve = curve->split(new_curve_name, start_time, duration); new_curve = curve->split(new_curve_name, start_time, duration);
} }

View File

@@ -32,7 +32,7 @@
#include "KRAnimationCurveManager.h" #include "KRAnimationCurveManager.h"
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
KRAnimationCurveManager::KRAnimationCurveManager(KRContext &context) : KRContextObject(context) KRAnimationCurveManager::KRAnimationCurveManager(KRContext &context) : KRResourceManager(context)
{ {
} }
@@ -48,6 +48,21 @@ void KRAnimationCurveManager::deleteAnimationCurve(KRAnimationCurve *curve) {
delete curve; delete curve;
} }
KRResource* KRAnimationCurveManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("kranimationcurve") == 0) {
return loadAnimationCurve(name, data);
}
return nullptr;
}
KRResource* KRAnimationCurveManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("kranimationcurve") == 0) {
return getAnimationCurve(name);
}
return nullptr;
}
KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) { KRAnimationCurve *KRAnimationCurveManager::loadAnimationCurve(const std::string &name, KRDataBlock *data) {
KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data); KRAnimationCurve *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
if(pAnimationCurve) { if(pAnimationCurve) {

View File

@@ -34,17 +34,22 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRAnimationCurve.h" #include "KRAnimationCurve.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
using std::map; using std::map;
class KRAnimationCurveManager : public KRContextObject { class KRAnimationCurveManager : public KRResourceManager {
public: public:
KRAnimationCurveManager(KRContext &context); KRAnimationCurveManager(KRContext &context);
virtual ~KRAnimationCurveManager(); virtual ~KRAnimationCurveManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimationCurve *loadAnimationCurve(const std::string &name, KRDataBlock *data); KRAnimationCurve *loadAnimationCurve(const std::string &name, KRDataBlock *data);
KRAnimationCurve *getAnimationCurve(const std::string &name); KRAnimationCurve *getAnimationCurve(const std::string &name);
void addAnimationCurve(KRAnimationCurve *new_animation_curve); void addAnimationCurve(KRAnimationCurve *new_animation_curve);

View File

@@ -32,7 +32,7 @@
#include "KRAnimationManager.h" #include "KRAnimationManager.h"
#include "KRAnimation.h" #include "KRAnimation.h"
KRAnimationManager::KRAnimationManager(KRContext &context) : KRContextObject(context) KRAnimationManager::KRAnimationManager(KRContext &context) : KRResourceManager(context)
{ {
} }
@@ -81,6 +81,20 @@ void KRAnimationManager::endFrame(float deltaTime)
} }
KRResource* KRAnimationManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("kranimation") == 0) {
return loadAnimation(name.c_str(), data);
}
return nullptr;
}
KRResource* KRAnimationManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("kranimation") == 0) {
return getAnimation(name.c_str());
}
return nullptr;
}
KRAnimation *KRAnimationManager::loadAnimation(const char *szName, KRDataBlock *data) { KRAnimation *KRAnimationManager::loadAnimation(const char *szName, KRDataBlock *data) {
KRAnimation *pAnimation = KRAnimation::Load(*m_pContext, szName, data); KRAnimation *pAnimation = KRAnimation::Load(*m_pContext, szName, data);

View File

@@ -34,16 +34,21 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRAnimation.h" #include "KRAnimation.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
class KRAnimationManager : public KRContextObject { class KRAnimationManager : public KRResourceManager {
public: public:
KRAnimationManager(KRContext &context); KRAnimationManager(KRContext &context);
virtual ~KRAnimationManager(); virtual ~KRAnimationManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRAnimation *loadAnimation(const char *szName, KRDataBlock *data); KRAnimation *loadAnimation(const char *szName, KRDataBlock *data);
KRAnimation *getAnimation(const char *szName); KRAnimation *getAnimation(const char *szName);

File diff suppressed because it is too large Load Diff

View File

@@ -34,6 +34,8 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
#include "KRAudioSource.h" #include "KRAudioSource.h"
@@ -90,10 +92,13 @@ typedef struct {
KRAudioSample *reverb_sample; KRAudioSample *reverb_sample;
} siren_reverb_zone_weight_info; } siren_reverb_zone_weight_info;
class KRAudioManager : public KRContextObject { class KRAudioManager : public KRResourceManager {
public: public:
KRAudioManager(KRContext &context); KRAudioManager(KRContext &context);
virtual ~KRAudioManager(); virtual ~KRAudioManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
unordered_map<std::string, KRAudioSample *> &getSounds(); unordered_map<std::string, KRAudioSample *> &getSounds();
@@ -238,7 +243,7 @@ private:
unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights; unordered_map<std::string, siren_reverb_zone_weight_info> m_reverb_zone_weights;
float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights float m_reverb_zone_total_weight = 0.0f; // For normalizing zone weights
boost::signals2::mutex m_mutex; std::mutex m_mutex;
#ifdef __APPLE__ #ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info; mach_timebase_info_data_t m_timebase_info;
#endif #endif

View File

@@ -84,7 +84,7 @@ int KRAudioSample::getChannelCount()
return m_channelsPerFrame; return m_channelsPerFrame;
} }
int KRAudioSample::getFrameCount() __int64_t KRAudioSample::getFrameCount()
{ {
loadInfo(); loadInfo();
//return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate); //return (int)((__int64_t)m_totalFrames * (__int64_t)frame_rate / (__int64_t)m_frameRate);
@@ -113,7 +113,7 @@ float KRAudioSample::sample(int frame_offset, int frame_rate, int channel)
if(buffer_index >= m_bufferCount) { if(buffer_index >= m_bufferCount) {
return 0.0f; // Past the end of the recording return 0.0f; // Past the end of the recording
} else { } else {
int buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer; __int64_t buffer_offset = frame_offset - buffer_index * maxFramesPerBuffer;
KRAudioBuffer *buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index); KRAudioBuffer *buffer = getContext().getAudioManager()->getBuffer(*this, buffer_index);
if(buffer == NULL) { if(buffer == NULL) {
@@ -132,12 +132,12 @@ void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel,
{ {
loadInfo(); loadInfo();
m_last_frame_used = getContext().getAudioManager()->getAudioFrame(); m_last_frame_used = (int)getContext().getAudioManager()->getAudioFrame();
if(loop) { if(loop) {
int buffer_offset = 0; int buffer_offset = 0;
int frames_left = frame_count; int frames_left = frame_count;
int sample_length = getFrameCount(); int sample_length = (int)getFrameCount();
while(frames_left) { while(frames_left) {
int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length); int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % sample_length);
if(next_frame + frames_left >= sample_length) { if(next_frame + frames_left >= sample_length) {
@@ -160,8 +160,8 @@ void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel,
// Range is entirely after the sample // Range is entirely after the sample
memset(buffer, 0, frame_count * sizeof(float)); memset(buffer, 0, frame_count * sizeof(float));
} else { } else {
int start_frame = frame_offset < 0 ? 0 : frame_offset; int start_frame = (int)(frame_offset < 0 ? 0 : frame_offset);
int prefix_frames = frame_offset < 0 ? -frame_offset : 0; int prefix_frames = (int)(frame_offset < 0 ? -frame_offset : 0);
if(prefix_frames > 0) { if(prefix_frames > 0) {
// Prefix with padding of 0's // Prefix with padding of 0's
memset(buffer, 0, prefix_frames * sizeof(float)); memset(buffer, 0, prefix_frames * sizeof(float));
@@ -386,7 +386,7 @@ KRAudioBuffer *KRAudioSample::getBuffer(int index)
void KRAudioSample::_endFrame() void KRAudioSample::_endFrame()
{ {
const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500; const __int64_t AUDIO_SAMPLE_EXPIRY_FRAMES = 500;
long current_frame = getContext().getAudioManager()->getAudioFrame(); __int64_t current_frame = getContext().getAudioManager()->getAudioFrame();
if(current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) { if(current_frame > m_last_frame_used + AUDIO_SAMPLE_EXPIRY_FRAMES) {
closeFile(); closeFile();
} }

View File

@@ -1,113 +1,113 @@
// //
// KRAudioSample.h // KRAudioSample.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#ifndef KRAUDIOSAMPLE_H #ifndef KRAUDIOSAMPLE_H
#define KRAUDIOSAMPLE_H #define KRAUDIOSAMPLE_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
#include "KRResource.h" #include "KRResource.h"
class KRAudioBuffer; class KRAudioBuffer;
class KRAudioSample : public KRResource { class KRAudioSample : public KRResource {
public: public:
KRAudioSample(KRContext &context, std::string name, std::string extension); KRAudioSample(KRContext &context, std::string name, std::string extension);
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data); KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
virtual ~KRAudioSample(); virtual ~KRAudioSample();
virtual std::string getExtension(); virtual std::string getExtension();
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock &data);
float getDuration(); float getDuration();
KRAudioBuffer *getBuffer(int index); KRAudioBuffer *getBuffer(int index);
int getBufferCount(); int getBufferCount();
// Siren audio engine interface // Siren audio engine interface
int getChannelCount(); int getChannelCount();
int getFrameCount(); __int64_t getFrameCount();
float sample(int frame_offset, int frame_rate, int channel); float sample(int frame_offset, int frame_rate, int channel);
void sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop); void sample(__int64_t frame_offset, int frame_count, int channel, float *buffer, float amplitude, bool loop);
void _endFrame(); void _endFrame();
private: private:
long m_last_frame_used; __int64_t m_last_frame_used;
std::string m_extension; std::string m_extension;
KRDataBlock *m_pData; KRDataBlock *m_pData;
#ifdef __APPLE__ #ifdef __APPLE__
// Apple Audio Toolbox // Apple Audio Toolbox
AudioFileID m_audio_file_id; AudioFileID m_audio_file_id;
ExtAudioFileRef m_fileRef; ExtAudioFileRef m_fileRef;
static OSStatus ReadProc( // AudioFile_ReadProc static OSStatus ReadProc( // AudioFile_ReadProc
void * inClientData, void * inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
void * buffer, void * buffer,
UInt32 * actualCount); UInt32 * actualCount);
static OSStatus WriteProc( // AudioFile_WriteProc static OSStatus WriteProc( // AudioFile_WriteProc
void * inClientData, void * inClientData,
SInt64 inPosition, SInt64 inPosition,
UInt32 requestCount, UInt32 requestCount,
const void *buffer, const void *buffer,
UInt32 * actualCount); UInt32 * actualCount);
static SInt64 GetSizeProc( // AudioFile_GetSizeProc static SInt64 GetSizeProc( // AudioFile_GetSizeProc
void * inClientData); void * inClientData);
static OSStatus SetSizeProc( // AudioFile_SetSizeProc static OSStatus SetSizeProc( // AudioFile_SetSizeProc
void * inClientData, void * inClientData,
SInt64 inSize); SInt64 inSize);
#endif #endif
int m_bufferCount; int m_bufferCount;
__int64_t m_totalFrames; __int64_t m_totalFrames;
int m_frameRate; int m_frameRate;
int m_bytesPerFrame; int m_bytesPerFrame;
int m_channelsPerFrame; int m_channelsPerFrame;
void openFile(); void openFile();
void closeFile(); void closeFile();
void loadInfo(); void loadInfo();
static void PopulateBuffer(KRAudioSample *sound, int index, void *data); static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
}; };
#endif /* defined(KRAUDIOSAMPLE_H) */ #endif /* defined(KRAUDIOSAMPLE_H) */

View File

@@ -180,9 +180,9 @@ void KRAudioSource::render(KRCamera *pCamera, std::vector<KRPointLight *> &point
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
@@ -433,7 +433,7 @@ float KRAudioSource::getAudioTime()
void KRAudioSource::setAudioTime(float new_position) void KRAudioSource::setAudioTime(float new_position)
{ {
// Sets the audio playback position with units of floating point seconds. // Sets the audio playback position with units of floating point seconds.
setAudioFrame(new_position * 44100.0f); setAudioFrame((__int64_t)(new_position * 44100.0f));
} }
void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain) void KRAudioSource::sample(int frame_count, int channel, float *buffer, float gain)

View File

@@ -10,6 +10,7 @@
#define KRBEHAVIOR_H #define KRBEHAVIOR_H
#include <map> #include <map>
#include <string>
/* /*

View File

@@ -1,97 +1,97 @@
// //
// KRBone.cpp // KRBone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRBone.h" #include "KRBone.h"
#include "KRContext.h" #include "KRContext.h"
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name) KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
setScaleCompensation(true); setScaleCompensation(true);
} }
KRBone::~KRBone() KRBone::~KRBone()
{ {
} }
std::string KRBone::getElementName() { std::string KRBone::getElementName() {
return "bone"; return "bone";
} }
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
return e; return e;
} }
void KRBone::loadXML(tinyxml2::XMLElement *e) void KRBone::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
setScaleCompensation(true); setScaleCompensation(true);
} }
AABB KRBone::getBounds() { AABB KRBone::getBounds() {
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); // Only required for bone debug visualization
} }
void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRBone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
} }
} }
void KRBone::setBindPose(const Matrix4 &pose) void KRBone::setBindPose(const Matrix4 &pose)
{ {
m_bind_pose = pose; m_bind_pose = pose;
} }
const Matrix4 &KRBone::getBindPose() const Matrix4 &KRBone::getBindPose()
{ {
return m_bind_pose; return m_bind_pose;
} }

View File

@@ -54,14 +54,14 @@ KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : K
m_pData = pData; m_pData = pData;
__int64_t file_pos = 0; __int64_t file_pos = 0;
while(file_pos < m_pData->getSize()) { while(file_pos < (__int64_t)m_pData->getSize()) {
tar_header_type file_header; tar_header_type file_header;
m_pData->copy(&file_header, file_pos, sizeof(file_header)); m_pData->copy(&file_header, (int)file_pos, sizeof(file_header));
size_t file_size = strtol(file_header.file_size, NULL, 8); size_t file_size = strtol(file_header.file_size, NULL, 8);
file_pos += 512; // Skip past the header to the file contents file_pos += 512; // Skip past the header to the file contents
if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') { if(file_header.file_name[0] != '\0' && file_header.file_name[0] != '.') {
// We ignore the last two records in the tar file, which are zero'ed out tar_header structures // We ignore the last two records in the tar file, which are zero'ed out tar_header structures
KRDataBlock *pFileData = pData->getSubBlock(file_pos, file_size); KRDataBlock *pFileData = pData->getSubBlock((int)file_pos, (int)file_size);
context.loadResource(file_header.file_name, pFileData); context.loadResource(file_header.file_name, pFileData);
} }
file_pos += RoundUpSize(file_size); file_pos += RoundUpSize(file_size);
@@ -114,7 +114,7 @@ bool KRBundle::save(KRDataBlock &data) {
return true; return true;
} }
void KRBundle::append(KRResource &resource) KRDataBlock* KRBundle::append(KRResource &resource)
{ {
// Serialize resource to binary representation // Serialize resource to binary representation
KRDataBlock resource_data; KRDataBlock resource_data;
@@ -124,7 +124,7 @@ void KRBundle::append(KRResource &resource)
// Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive // Padding is added at the end of file to align next header to a 512 byte boundary. Padding at the end of the archive includes an additional 1024 bytes -- two zero-ed out file headers that mark the end of the archive
size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2; size_t padding_size = RoundUpSize(resource_data.getSize()) - resource_data.getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE * 2;
size_t resource_data_start = m_pData->getSize() + KRENGINE_KRBUNDLE_HEADER_SIZE;
m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here m_pData->expand(KRENGINE_KRBUNDLE_HEADER_SIZE + resource_data.getSize() + padding_size - KRENGINE_KRBUNDLE_HEADER_SIZE * 2); // We will overwrite the existing zero-ed out file headers that marked the end of the archive, so we don't have to include their size here
m_pData->lock(); m_pData->lock();
@@ -163,4 +163,7 @@ void KRBundle::append(KRResource &resource)
sprintf(file_header->checksum, "%07o", check_sum); sprintf(file_header->checksum, "%07o", check_sum);
m_pData->unlock(); m_pData->unlock();
KRDataBlock *pFileData = m_pData->getSubBlock((int)resource_data_start, (int)resource_data.getSize());
return pFileData;
} }

View File

@@ -44,7 +44,7 @@ public:
virtual bool save(const std::string& path); virtual bool save(const std::string& path);
virtual bool save(KRDataBlock &data); virtual bool save(KRDataBlock &data);
void append(KRResource &resource); KRDataBlock* append(KRResource &resource);
private: private:
KRDataBlock *m_pData; KRDataBlock *m_pData;

View File

@@ -33,7 +33,7 @@
#include "KRBundle.h" #include "KRBundle.h"
KRBundleManager::KRBundleManager(KRContext &context) : KRContextObject(context) { KRBundleManager::KRBundleManager(KRContext &context) : KRResourceManager(context) {
} }
@@ -44,6 +44,21 @@ KRBundleManager::~KRBundleManager() {
m_bundles.empty(); m_bundles.empty();
} }
KRResource* KRBundleManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("krbundle") == 0) {
return loadBundle(name.c_str() , data);
}
return nullptr;
}
KRResource* KRBundleManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("krbundle") == 0) {
return getBundle(name.c_str());
}
return nullptr;
}
KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData) KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData)
{ {
KRBundle *pBundle = new KRBundle(*m_pContext, szName, pData); KRBundle *pBundle = new KRBundle(*m_pContext, szName, pData);
@@ -51,6 +66,14 @@ KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData)
return pBundle; return pBundle;
} }
KRBundle *KRBundleManager::createBundle(const char *szName)
{
// TODO: Check for name conflicts
KRBundle *pBundle = new KRBundle(*m_pContext, szName);
m_bundles[szName] = pBundle;
return pBundle;
}
KRBundle *KRBundleManager::getBundle(const char *szName) { KRBundle *KRBundleManager::getBundle(const char *szName) {
return m_bundles[szName]; return m_bundles[szName];
} }

View File

@@ -33,6 +33,8 @@
#ifndef KRBUNDLEMANAGER_H #ifndef KRBUNDLEMANAGER_H
#define KRBUNDLEMANAGER_H #define KRBUNDLEMANAGER_H
#include "KRResourceManager.h"
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
@@ -40,13 +42,17 @@
class KRContext; class KRContext;
class KRBundle; class KRBundle;
class KRBundleManager : public KRContextObject { class KRBundleManager : public KRResourceManager {
public: public:
KRBundleManager(KRContext &context); KRBundleManager(KRContext &context);
~KRBundleManager(); ~KRBundleManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
KRBundle *loadBundle(const char *szName, KRDataBlock *pData); KRBundle *loadBundle(const char *szName, KRDataBlock *pData);
KRBundle *getBundle(const char *szName); KRBundle *getBundle(const char *szName);
KRBundle* createBundle(const char* szName);
std::vector<std::string> getBundleNames(); std::vector<std::string> getBundleNames();
unordered_map<std::string, KRBundle *> getBundles(); unordered_map<std::string, KRBundle *> getBundles();

File diff suppressed because it is too large Load Diff

View File

@@ -34,7 +34,7 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRShader.h" #include "KRPipeline.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRTexture.h" #include "KRTexture.h"
#include "KRContext.h" #include "KRContext.h"

View File

@@ -1,229 +1,229 @@
// //
// KRCollider.cpp // KRCollider.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRCollider.h" #include "KRCollider.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRMesh.h" #include "KRMesh.h"
KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) { KRCollider::KRCollider(KRScene &scene, std::string collider_name, std::string model_name, unsigned int layer_mask, float audio_occlusion) : KRNode(scene, collider_name) {
m_model_name = model_name; m_model_name = model_name;
m_layer_mask = layer_mask; m_layer_mask = layer_mask;
m_audio_occlusion = audio_occlusion; m_audio_occlusion = audio_occlusion;
} }
KRCollider::~KRCollider() { KRCollider::~KRCollider() {
} }
std::string KRCollider::getElementName() { std::string KRCollider::getElementName() {
return "collider"; return "collider";
} }
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str()); e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("layer_mask", m_layer_mask); e->SetAttribute("layer_mask", m_layer_mask);
e->SetAttribute("audio_occlusion", m_audio_occlusion); e->SetAttribute("audio_occlusion", m_audio_occlusion);
return e; return e;
} }
void KRCollider::loadXML(tinyxml2::XMLElement *e) { void KRCollider::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
m_model_name = e->Attribute("mesh"); m_model_name = e->Attribute("mesh");
m_layer_mask = 65535; m_layer_mask = 65535;
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) { if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
m_layer_mask = 65535; m_layer_mask = 65535;
} }
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
m_audio_occlusion = 1.0f; m_audio_occlusion = 1.0f;
} }
} }
void KRCollider::loadModel() { void KRCollider::loadModel() {
if(m_models.size() == 0) { if(m_models.size() == 0) {
m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first m_models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
if(m_models.size() > 0) { if(m_models.size() > 0) {
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
} }
} }
AABB KRCollider::getBounds() { AABB KRCollider::getBounds() {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
} else { } else {
return AABB::Infinite(); return AABB::Infinite();
} }
} }
bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set if(layer_mask & m_layer_mask ) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_models.size()) { if(m_models.size()) {
if(getBounds().intersectsLine(v0, v1)) { if(getBounds().intersectsLine(v0, v1)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0); Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1); Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
HitInfo hitinfo_model_space; HitInfo hitinfo_model_space;
if(hitinfo.didHit()) { if(hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition()); Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode()); hitinfo_model_space = HitInfo(hit_position_model_space, Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal()), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
} }
if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) { if(m_models[0]->lineCast(v0_model_space, v1_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()); Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this); hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_models.size()) { if(m_models.size()) {
if(getBounds().intersectsRay(v0, dir)) { if(getBounds().intersectsRay(v0, dir)) {
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0); Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir)); Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
HitInfo hitinfo_model_space; HitInfo hitinfo_model_space;
if(hitinfo.didHit()) { if(hitinfo.didHit()) {
Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition()); Vector3 hit_position_model_space = Matrix4::Dot(getInverseModelMatrix(), hitinfo.getPosition());
hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode()); hitinfo_model_space = HitInfo(hit_position_model_space, Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), hitinfo.getNormal())), (hit_position_model_space - v0_model_space).magnitude(), hitinfo.getNode());
} }
if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) { if(m_models[0]->rayCast(v0_model_space, dir_model_space, hitinfo_model_space)) {
Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition()); Vector3 hit_position_world_space = Matrix4::Dot(getModelMatrix(), hitinfo_model_space.getPosition());
hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this); hitinfo = HitInfo(hit_position_world_space, Vector3::Normalize(Matrix4::DotNoTranslate(getModelMatrix(), hitinfo_model_space.getNormal())), (hit_position_world_space - v0).magnitude(), this);
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask) bool KRCollider::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
{ {
if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set if(layer_mask & m_layer_mask) { // Only test if layer masks have a common bit set
loadModel(); loadModel();
if(m_models.size()) { if(m_models.size()) {
AABB sphereCastBounds = AABB::Create( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions AABB sphereCastBounds = AABB::Create( // TODO - Need to cache this; perhaps encasulate within a "spherecast" class to be passed through these functions
Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius),
Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius) Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)
); );
if(getBounds().intersects(sphereCastBounds)) { if(getBounds().intersects(sphereCastBounds)) {
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) { if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this); hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
return true; return true;
} }
} }
} }
} }
return false; return false;
} }
unsigned int KRCollider::getLayerMask() unsigned int KRCollider::getLayerMask()
{ {
return m_layer_mask; return m_layer_mask;
} }
void KRCollider::setLayerMask(unsigned int layer_mask) void KRCollider::setLayerMask(unsigned int layer_mask)
{ {
m_layer_mask = layer_mask; m_layer_mask = layer_mask;
} }
float KRCollider::getAudioOcclusion() float KRCollider::getAudioOcclusion()
{ {
return m_audio_occlusion; return m_audio_occlusion;
} }
void KRCollider::setAudioOcclusion(float audio_occlusion) void KRCollider::setAudioOcclusion(float audio_occlusion)
{ {
m_audio_occlusion = audio_occlusion; m_audio_occlusion = audio_occlusion;
} }
void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRCollider::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_COLLIDERS) {
loadModel(); loadModel();
if(m_models.size()) { if(m_models.size()) {
GL_PUSH_GROUP_MARKER("Debug Overlays"); GL_PUSH_GROUP_MARKER("Debug Overlays");
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) { for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
GL_POP_GROUP_MARKER; GL_POP_GROUP_MARKER;
} }
} }
} }

View File

@@ -12,12 +12,18 @@
#include "KRCamera.h" #include "KRCamera.h"
#include "KRAudioManager.h" #include "KRAudioManager.h"
#include "KRAudioSample.h" #include "KRAudioSample.h"
#include "KRBundle.h"
#if defined(ANDROID)
#include <chrono>
#include <unistd.h>
#endif
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#include <windows.h> #include <windows.h>
#endif #endif
int KRContext::KRENGINE_MAX_SHADER_HANDLES; int KRContext::KRENGINE_MAX_PIPELINE_HANDLES;
int KRContext::KRENGINE_GPU_MEM_MAX; int KRContext::KRENGINE_GPU_MEM_MAX;
int KRContext::KRENGINE_GPU_MEM_TARGET; int KRContext::KRENGINE_GPU_MEM_TARGET;
int KRContext::KRENGINE_MAX_TEXTURE_DIM; int KRContext::KRENGINE_MAX_TEXTURE_DIM;
@@ -33,6 +39,8 @@ int KRContext::KRENGINE_SYS_PAGE_SIZE;
#elif defined(_WIN32) || defined(_WIN64) #elif defined(_WIN32) || defined(_WIN64)
#elif defined(ANDROID)
#else #else
#error Unsupported Platform #error Unsupported Platform
@@ -47,8 +55,13 @@ const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
KRContext::log_callback *KRContext::s_log_callback = NULL; KRContext::log_callback *KRContext::s_log_callback = NULL;
void *KRContext::s_log_callback_user_data = NULL; void *KRContext::s_log_callback_user_data = NULL;
KRContext::KRContext() : m_streamer(*this) KRContext::KRContext(const KrInitializeInfo* initializeInfo)
: m_streamer(*this)
, m_vulkanInstance(VK_NULL_HANDLE)
, m_resourceMapSize(initializeInfo->resourceMapSize)
{ {
m_resourceMap = (KRResource **)malloc(sizeof(KRResource*) * m_resourceMapSize);
memset(m_resourceMap, 0, m_resourceMapSize * sizeof(KRResource*));
m_streamingEnabled = false; m_streamingEnabled = false;
#ifdef __APPLE__ #ifdef __APPLE__
mach_timebase_info(&m_timebase_info); mach_timebase_info(&m_timebase_info);
@@ -61,15 +74,17 @@ KRContext::KRContext() : m_streamer(*this)
m_absolute_time = 0.0f; m_absolute_time = 0.0f;
m_pBundleManager = new KRBundleManager(*this); m_pBundleManager = new KRBundleManager(*this);
m_pShaderManager = new KRShaderManager(*this); m_pPipelineManager = new KRPipelineManager(*this);
m_pTextureManager = new KRTextureManager(*this); m_pTextureManager = new KRTextureManager(*this);
m_pMaterialManager = new KRMaterialManager(*this, m_pTextureManager, m_pShaderManager); m_pMaterialManager = new KRMaterialManager(*this, m_pTextureManager, m_pPipelineManager);
m_pMeshManager = new KRMeshManager(*this); m_pMeshManager = new KRMeshManager(*this);
m_pSceneManager = new KRSceneManager(*this); m_pSceneManager = new KRSceneManager(*this);
m_pAnimationManager = new KRAnimationManager(*this); m_pAnimationManager = new KRAnimationManager(*this);
m_pAnimationCurveManager = new KRAnimationCurveManager(*this); m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
m_pSoundManager = new KRAudioManager(*this); m_pSoundManager = new KRAudioManager(*this);
m_pUnknownManager = new KRUnknownManager(*this); m_pUnknownManager = new KRUnknownManager(*this);
m_pShaderManager = new KRShaderManager(*this);
m_pSourceManager = new KRSourceManager(*this);
m_streamingEnabled = true; m_streamingEnabled = true;
@@ -81,7 +96,7 @@ KRContext::KRContext() : m_streamer(*this)
KRENGINE_SYS_ALLOCATION_GRANULARITY = winSysInfo.dwAllocationGranularity; KRENGINE_SYS_ALLOCATION_GRANULARITY = winSysInfo.dwAllocationGranularity;
KRENGINE_SYS_PAGE_SIZE = winSysInfo.dwPageSize; KRENGINE_SYS_PAGE_SIZE = winSysInfo.dwPageSize;
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
KRENGINE_SYS_PAGE_SIZE = getpagesize(); KRENGINE_SYS_PAGE_SIZE = getpagesize();
KRENGINE_SYS_ALLOCATION_GRANULARITY = KRENGINE_SYS_PAGE_SIZE; KRENGINE_SYS_ALLOCATION_GRANULARITY = KRENGINE_SYS_PAGE_SIZE;
@@ -94,7 +109,6 @@ KRContext::KRContext() : m_streamer(*this)
} }
KRContext::~KRContext() { KRContext::~KRContext() {
if(m_pSceneManager) { if(m_pSceneManager) {
delete m_pSceneManager; delete m_pSceneManager;
m_pSceneManager = NULL; m_pSceneManager = NULL;
@@ -115,9 +129,9 @@ KRContext::~KRContext() {
m_pMaterialManager = NULL; m_pMaterialManager = NULL;
} }
if(m_pShaderManager) { if(m_pPipelineManager) {
delete m_pShaderManager; delete m_pPipelineManager;
m_pShaderManager = NULL; m_pPipelineManager = NULL;
} }
if(m_pAnimationManager) { if(m_pAnimationManager) {
@@ -135,6 +149,11 @@ KRContext::~KRContext() {
m_pSoundManager = NULL; m_pSoundManager = NULL;
} }
if(m_pSourceManager) {
delete m_pSourceManager;
m_pSourceManager = NULL;
}
if(m_pUnknownManager) { if(m_pUnknownManager) {
delete m_pUnknownManager; delete m_pUnknownManager;
m_pUnknownManager = NULL; m_pUnknownManager = NULL;
@@ -147,6 +166,10 @@ KRContext::~KRContext() {
} }
destroyDeviceContexts(); destroyDeviceContexts();
if (m_resourceMap) {
delete m_resourceMap;
m_resourceMap = NULL;
}
} }
void KRContext::SetLogCallback(log_callback *log_callback, void *user_data) void KRContext::SetLogCallback(log_callback *log_callback, void *user_data)
@@ -187,8 +210,8 @@ KRTextureManager *KRContext::getTextureManager() {
KRMaterialManager *KRContext::getMaterialManager() { KRMaterialManager *KRContext::getMaterialManager() {
return m_pMaterialManager; return m_pMaterialManager;
} }
KRShaderManager *KRContext::getShaderManager() { KRPipelineManager *KRContext::getPipelineManager() {
return m_pShaderManager; return m_pPipelineManager;
} }
KRMeshManager *KRContext::getMeshManager() { KRMeshManager *KRContext::getMeshManager() {
return m_pMeshManager; return m_pMeshManager;
@@ -202,13 +225,17 @@ KRAnimationCurveManager *KRContext::getAnimationCurveManager() {
KRAudioManager *KRContext::getAudioManager() { KRAudioManager *KRContext::getAudioManager() {
return m_pSoundManager; return m_pSoundManager;
} }
KRShaderManager *KRContext::getShaderManager() {
return m_pShaderManager;
}
KRSourceManager *KRContext::getSourceManager() {
return m_pSourceManager;
}
KRUnknownManager *KRContext::getUnknownManager() { KRUnknownManager *KRContext::getUnknownManager() {
return m_pUnknownManager; return m_pUnknownManager;
} }
std::vector<KRResource *> KRContext::getResources() std::vector<KRResource *> KRContext::getResources()
{ {
std::vector<KRResource *> resources; std::vector<KRResource *> resources;
for(unordered_map<std::string, KRScene *>::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) { for(unordered_map<std::string, KRScene *>::iterator itr = m_pSceneManager->getScenes().begin(); itr != m_pSceneManager->getScenes().end(); itr++) {
@@ -232,6 +259,20 @@ std::vector<KRResource *> KRContext::getResources()
for(unordered_map<std::string, KRAudioSample *>::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) { for(unordered_map<std::string, KRAudioSample *>::iterator itr = m_pSoundManager->getSounds().begin(); itr != m_pSoundManager->getSounds().end(); itr++) {
resources.push_back((*itr).second); resources.push_back((*itr).second);
} }
unordered_map<std::string, unordered_map<std::string, KRSource *> > sources = m_pSourceManager->getSources();
for(unordered_map<std::string, unordered_map<std::string, KRSource *> >::iterator itr = sources.begin(); itr != sources.end(); itr++) {
for(unordered_map<std::string, KRSource *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
resources.push_back((*itr2).second);
}
}
unordered_map<std::string, unordered_map<std::string, KRShader *> > shaders = m_pShaderManager->getShaders();
for(unordered_map<std::string, unordered_map<std::string, KRShader *> >::iterator itr = shaders.begin(); itr != shaders.end(); itr++) {
for(unordered_map<std::string, KRShader *>::iterator itr2 = (*itr).second.begin(); itr2 != (*itr).second.end(); itr2++) {
resources.push_back((*itr2).second);
}
}
unordered_map<std::string, unordered_map<std::string, KRUnknown *> > unknowns = m_pUnknownManager->getUnknowns(); unordered_map<std::string, unordered_map<std::string, KRUnknown *> > unknowns = m_pUnknownManager->getUnknowns();
for(unordered_map<std::string, unordered_map<std::string, KRUnknown *> >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) { for(unordered_map<std::string, unordered_map<std::string, KRUnknown *> >::iterator itr = unknowns.begin(); itr != unknowns.end(); itr++) {
@@ -240,66 +281,201 @@ std::vector<KRResource *> KRContext::getResources()
} }
} }
// FINDME, TODO - Not yet exporting shaders, as they are currently only being used as standard Kraken assets. In the future people may want their custom shaders to be exported.
return resources; return resources;
} }
void KRContext::loadResource(const std::string &file_name, KRDataBlock *data) { KRResource* KRContext::loadResource(const std::string &file_name, KRDataBlock *data) {
std::string name = KRResource::GetFileBase(file_name); std::string name = KRResource::GetFileBase(file_name);
std::string extension = KRResource::GetFileExtension(file_name); std::string extension = KRResource::GetFileExtension(file_name);
KRResource *resource = nullptr;
// fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str()); // fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str());
if(extension.compare("krbundle") == 0) { if(extension.compare("krbundle") == 0) {
m_pBundleManager->loadBundle(name.c_str(), data); resource = m_pBundleManager->loadBundle(name.c_str(), data);
} else if(extension.compare("krmesh") == 0) { } else if(extension.compare("krmesh") == 0) {
m_pMeshManager->loadModel(name.c_str(), data); resource = m_pMeshManager->loadModel(name.c_str(), data);
} else if(extension.compare("krscene") == 0) { } else if(extension.compare("krscene") == 0) {
m_pSceneManager->loadScene(name.c_str(), data); resource = m_pSceneManager->loadScene(name.c_str(), data);
} else if(extension.compare("kranimation") == 0) { } else if(extension.compare("kranimation") == 0) {
m_pAnimationManager->loadAnimation(name.c_str(), data); resource = m_pAnimationManager->loadAnimation(name.c_str(), data);
} else if(extension.compare("kranimationcurve") == 0) { } else if(extension.compare("kranimationcurve") == 0) {
m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data); resource = m_pAnimationCurveManager->loadAnimationCurve(name.c_str(), data);
} else if(extension.compare("pvr") == 0) { } else if(extension.compare("pvr") == 0) {
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("ktx") == 0) { } else if(extension.compare("ktx") == 0) {
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("tga") == 0) { } else if(extension.compare("tga") == 0) {
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data); resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("vsh") == 0) { } else if(extension.compare("spv") == 0) {
m_pShaderManager->loadVertexShader(name.c_str(), data); // SPIR-V shader binary
} else if(extension.compare("fsh") == 0) { resource = m_pShaderManager->load(name, extension, data);
m_pShaderManager->loadFragmentShader(name.c_str(), data); } else if(extension.compare("vert") == 0) {
// vertex shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("frag") == 0) {
// fragment shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("tesc") == 0) {
// tessellation control shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("tese") == 0) {
// tessellation evaluation shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("geom") == 0) {
// geometry shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("comp") == 0) {
// compute shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("mesh") == 0) {
// mesh shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("task") == 0) {
// task shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rgen") == 0) {
// ray generation shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rint") == 0) {
// ray intersection shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rahit") == 0) {
// ray any hit shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rchit") == 0) {
// ray closest hit shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rmiss") == 0) {
// ray miss shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("rcall") == 0) {
// ray callable shader
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("glsl") == 0) {
// glsl included by other shaders
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("options") == 0) {
// shader pre-processor options definition file
resource = m_pSourceManager->load(name, extension, data);
} else if(extension.compare("mtl") == 0) { } else if(extension.compare("mtl") == 0) {
m_pMaterialManager->load(name.c_str(), data); resource = m_pMaterialManager->load(name.c_str(), data);
} else if(extension.compare("mp3") == 0) { } else if(extension.compare("mp3") == 0) {
m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("wav") == 0) { } else if(extension.compare("wav") == 0) {
m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("aac") == 0) { } else if(extension.compare("aac") == 0) {
m_pSoundManager->load(name.c_str(), extension, data); resource = m_pSoundManager->load(name.c_str(), extension, data);
} else if(extension.compare("obj") == 0) { } else if(extension.compare("obj") == 0) {
KRResource::LoadObj(*this, file_name); resource = KRResource::LoadObj(*this, file_name);
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE
/*
// FINDME, TODO, HACK! - Uncomment
} else if(extension.compare("fbx") == 0) { } else if(extension.compare("fbx") == 0) {
KRResource::LoadFbx(*this, file_name); resource = KRResource::LoadFbx(*this, file_name);
*/
} else if(extension.compare("blend") == 0) { } else if(extension.compare("blend") == 0) {
KRResource::LoadBlenderScene(*this, file_name); resource = KRResource::LoadBlenderScene(*this, file_name);
#endif #endif
} else { } else {
m_pUnknownManager->load(name, extension, data); resource = m_pUnknownManager->load(name, extension, data);
} }
return resource;
} }
void KRContext::loadResource(std::string path) { KrResult KRContext::loadResource(const KrLoadResourceInfo* loadResourceInfo) {
KRDataBlock *data = new KRDataBlock(); if (loadResourceInfo->resourceHandle < 0 || loadResourceInfo->resourceHandle >= m_resourceMapSize) {
if(data->load(path)) { return KR_ERROR_OUT_OF_BOUNDS;
loadResource(path, data);
} else {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", path.c_str());
delete data;
} }
KRDataBlock *data = new KRDataBlock();
if(!data->load(loadResourceInfo->pResourcePath)) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", loadResourceInfo->pResourcePath);
delete data;
return KR_ERROR_UNEXPECTED;
}
KRResource *resource = loadResource(loadResourceInfo->pResourcePath, data);
m_resourceMap[loadResourceInfo->resourceHandle] = resource;
return KR_SUCCESS;
}
KrResult KRContext::unloadResource(const KrUnloadResourceInfo* unloadResourceInfo)
{
if (unloadResourceInfo->resourceHandle < 0 || unloadResourceInfo->resourceHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
KRResource* resource = m_resourceMap[unloadResourceInfo->resourceHandle];
if (resource == nullptr) {
return KR_ERROR_NOT_MAPPED;
}
// TODO - Need to implement unloading logic
return KR_ERROR_NOT_IMPLEMENTED;
}
KrResult KRContext::mapResource(const KrMapResourceInfo* mapResourceInfo)
{
if (mapResourceInfo->resourceHandle < 0 || mapResourceInfo->resourceHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
/*
KRResource* resource = loadResource(loadResourceInfo->pResourcePath, data);
m_resourceMap[loadResourceInfo->resourceHandle] = resource;
return KR_SUCCESS;
*/
// TODO - Need to implement mapping logic
return KR_ERROR_NOT_IMPLEMENTED;
}
KrResult KRContext::createBundle(const KrCreateBundleInfo* createBundleInfo)
{
if (createBundleInfo->resourceHandle < 0 || createBundleInfo->resourceHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
KRResource* bundle = m_pBundleManager->createBundle(createBundleInfo->pBundleName);
m_resourceMap[createBundleInfo->resourceHandle] = bundle;
return KR_SUCCESS;
}
KrResult KRContext::moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo)
{
if (moveToBundleInfo->bundleHandle < 0 || moveToBundleInfo->bundleHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
if (moveToBundleInfo->resourceHandle < 0 || moveToBundleInfo->resourceHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
KRResource* resource = m_resourceMap[moveToBundleInfo->resourceHandle];
if (resource == nullptr) {
return KR_ERROR_NOT_MAPPED;
}
KRResource* bundleResource = m_resourceMap[moveToBundleInfo->bundleHandle];
if (bundleResource == nullptr) {
return KR_ERROR_NOT_MAPPED;
}
KRBundle* bundle = dynamic_cast<KRBundle*>(bundleResource);
if (bundle == nullptr) {
return KR_ERROR_INCORRECT_TYPE;
}
return resource->moveToBundle(bundle);
}
KrResult KRContext::saveResource(const KrSaveResourceInfo* saveResourceInfo)
{
if (saveResourceInfo->resourceHandle < 0 || saveResourceInfo->resourceHandle >= m_resourceMapSize) {
return KR_ERROR_OUT_OF_BOUNDS;
}
KRResource* resource = m_resourceMap[saveResourceInfo->resourceHandle];
if (resource == nullptr) {
return KR_ERROR_NOT_MAPPED;
}
if (resource->save(saveResourceInfo->pResourcePath)) {
return KR_SUCCESS;
}
return KR_ERROR_UNEXPECTED;
} }
void KRContext::detectExtensions() { void KRContext::detectExtensions() {
@@ -343,7 +519,10 @@ float KRContext::getAbsoluteTime() const
long KRContext::getAbsoluteTimeMilliseconds() long KRContext::getAbsoluteTimeMilliseconds()
{ {
#ifdef __APPLE__ #if defined(ANDROID)
return std::chrono::duration_cast< std::chrono::milliseconds >(
std::chrono::system_clock::now().time_since_epoch()).count();
#elif defined(__APPLE__)
return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow return (long)(mach_absolute_time() / 1000 * m_timebase_info.numer / m_timebase_info.denom); // Division done first to avoid potential overflow
#else #else
return (long)GetTickCount64(); return (long)GetTickCount64();
@@ -387,20 +566,20 @@ void KRContext::getMemoryStats(long &free_memory)
void KRContext::doStreaming() void KRContext::doStreaming()
{ {
if(m_streamingEnabled) { if (m_streamingEnabled) {
/* /*
long free_memory = KRENGINE_GPU_MEM_TARGET; long free_memory = KRENGINE_GPU_MEM_TARGET;
long total_memory = KRENGINE_GPU_MEM_MAX; long total_memory = KRENGINE_GPU_MEM_MAX;
*/ */
/* /*
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
// FINDME, TODO, HACK! - Experimental code, need to expose through engine parameters // FINDME, TODO, HACK! - Experimental code, need to expose through engine parameters
const long KRENGINE_RESERVE_MEMORY = 0x4000000; // 64MB const long KRENGINE_RESERVE_MEMORY = 0x4000000; // 64MB
getMemoryStats(free_memory); getMemoryStats(free_memory);
free_memory = KRCLAMP(free_memory - KRENGINE_RESERVE_MEMORY, 0, KRENGINE_GPU_MEM_TARGET); free_memory = KRCLAMP(free_memory - KRENGINE_RESERVE_MEMORY, 0, KRENGINE_GPU_MEM_TARGET);
total_memory = KRMIN(KRENGINE_GPU_MEM_MAX, free_memory * 3 / 4 + m_pTextureManager->getMemUsed() + m_pMeshManager->getMemUsed()); total_memory = KRMIN(KRENGINE_GPU_MEM_MAX, free_memory * 3 / 4 + m_pTextureManager->getMemUsed() + m_pMeshManager->getMemUsed());
#endif #endif
*/ */
/* /*
@@ -411,7 +590,7 @@ void KRContext::doStreaming()
free_memory = 0; free_memory = 0;
} }
*/ */
/* /*
// FINDME, TODO - Experimental code, need to expose through engine parameters // FINDME, TODO - Experimental code, need to expose through engine parameters
const long MEMORY_WARNING_THROTTLE2_FRAMES = 30; const long MEMORY_WARNING_THROTTLE2_FRAMES = 30;
@@ -421,31 +600,75 @@ void KRContext::doStreaming()
free_memory /= 2; free_memory /= 2;
} }
*/ */
/* /*
m_pMeshManager->doStreaming(total_memory, free_memory); m_pMeshManager->doStreaming(total_memory, free_memory);
m_pTextureManager->doStreaming(total_memory, free_memory); m_pTextureManager->doStreaming(total_memory, free_memory);
*/ */
long streaming_start_frame = m_current_frame; long streaming_start_frame = m_current_frame;
long memoryRemaining = KRENGINE_GPU_MEM_TARGET; long memoryRemaining = KRENGINE_GPU_MEM_TARGET;
long memoryRemainingThisFrame = KRENGINE_GPU_MEM_MAX - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed(); long memoryRemainingThisFrame = KRENGINE_GPU_MEM_MAX - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed();
long memoryRemainingThisFrameStart = memoryRemainingThisFrame; long memoryRemainingThisFrameStart = memoryRemainingThisFrame;
m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame); m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame); m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
if(memoryRemainingThisFrame == memoryRemainingThisFrameStart && memoryRemainingThisFrame > 0) { if (memoryRemainingThisFrame == memoryRemainingThisFrameStart && memoryRemainingThisFrame > 0) {
m_last_fully_streamed_frame = streaming_start_frame; m_last_fully_streamed_frame = streaming_start_frame;
}
} }
}
} }
void KRContext::receivedMemoryWarning() void KRContext::receivedMemoryWarning()
{ {
m_last_memory_warning_frame = m_current_frame; m_last_memory_warning_frame = m_current_frame;
} }
void
KRContext::createDeviceContexts()
{
// initialize the VkApplicationInfo structure
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pNext = NULL;
app_info.pApplicationName = "Test"; // TODO - Change Me!
app_info.applicationVersion = 1;
app_info.pEngineName = "Kraken Engine";
app_info.engineVersion = 1;
app_info.apiVersion = VK_API_VERSION_1_0;
// initialize the VkInstanceCreateInfo structure
VkInstanceCreateInfo inst_info = {};
inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_info.pNext = NULL;
inst_info.flags = 0;
inst_info.pApplicationInfo = &app_info;
inst_info.enabledExtensionCount = 0;
inst_info.ppEnabledExtensionNames = NULL;
inst_info.enabledLayerCount = 0;
inst_info.ppEnabledLayerNames = NULL;
VkResult res = vkCreateInstance(&inst_info, NULL, &m_vulkanInstance);
if (res != VK_SUCCESS) {
destroyDeviceContexts();
}
}
void
KRContext::destroyDeviceContexts()
{
if (m_vulkanInstance != VK_NULL_HANDLE) {
vkDestroyInstance(m_vulkanInstance, NULL);
m_vulkanInstance = VK_NULL_HANDLE;
}
}
void
KRContext::activateStreamerContext()
{
}

View File

@@ -1,140 +1,157 @@
// //
// KRContext.h // KRContext.h
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-12. // Created by Kearwood Gilbert on 12-04-12.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#ifndef KREngine_KRContext_h #ifndef KREngine_KRContext_h
#define KREngine_KRContext_h #define KREngine_KRContext_h
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRBundleManager.h" #include "KRBundleManager.h"
#include "KRSceneManager.h" #include "KRSceneManager.h"
#include "KRTextureManager.h" #include "KRTextureManager.h"
#include "KRMaterialManager.h" #include "KRMaterialManager.h"
#include "KRShaderManager.h" #include "KRPipelineManager.h"
#include "KRMeshManager.h" #include "KRMeshManager.h"
#include "KRAnimationManager.h" #include "KRAnimationManager.h"
#include "KRAnimationCurveManager.h" #include "KRAnimationCurveManager.h"
#include "KRUnknownManager.h" #include "KRUnknownManager.h"
#include "KRStreamer.h" #include "KRShaderManager.h"
#include "KRSourceManager.h"
class KRAudioManager; #include "KRStreamer.h"
class KRContext { class KRAudioManager;
public:
static int KRENGINE_MAX_SHADER_HANDLES; class KRContext {
static int KRENGINE_GPU_MEM_MAX; public:
static int KRENGINE_GPU_MEM_TARGET; static int KRENGINE_MAX_PIPELINE_HANDLES;
static int KRENGINE_MAX_TEXTURE_DIM; static int KRENGINE_GPU_MEM_MAX;
static int KRENGINE_MIN_TEXTURE_DIM; static int KRENGINE_GPU_MEM_TARGET;
static int KRENGINE_PRESTREAM_DISTANCE; static int KRENGINE_MAX_TEXTURE_DIM;
static int KRENGINE_SYS_ALLOCATION_GRANULARITY; static int KRENGINE_MIN_TEXTURE_DIM;
static int KRENGINE_SYS_PAGE_SIZE; static int KRENGINE_PRESTREAM_DISTANCE;
static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
static int KRENGINE_SYS_PAGE_SIZE;
KRContext();
~KRContext();
KRContext(const KrInitializeInfo* initializeInfo);
void loadResource(const std::string &file_name, KRDataBlock *data); ~KRContext();
void loadResource(std::string path);
KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
KRBundleManager *getBundleManager(); KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
KRSceneManager *getSceneManager(); KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
KRTextureManager *getTextureManager(); KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
KRMaterialManager *getMaterialManager(); KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
KRShaderManager *getShaderManager(); KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
KRMeshManager *getMeshManager();
KRAnimationManager *getAnimationManager(); KRResource* loadResource(const std::string &file_name, KRDataBlock *data);
KRAnimationCurveManager *getAnimationCurveManager();
KRAudioManager *getAudioManager();
KRUnknownManager *getUnknownManager(); KRBundleManager *getBundleManager();
KRSceneManager *getSceneManager();
KRCamera *createCamera(int width, int height); KRTextureManager *getTextureManager();
KRMaterialManager *getMaterialManager();
enum { KRPipelineManager *getPipelineManager();
KRENGINE_GL_EXT_texture_storage, KRMeshManager *getMeshManager();
KRENGINE_NUM_EXTENSIONS KRAnimationManager *getAnimationManager();
}; KRAnimationCurveManager *getAnimationCurveManager();
KRAudioManager *getAudioManager();
static const char * extension_names[KRENGINE_NUM_EXTENSIONS]; KRUnknownManager *getUnknownManager();
static bool extension_available[KRENGINE_NUM_EXTENSIONS]; KRShaderManager *getShaderManager();
KRSourceManager *getSourceManager();
void startFrame(float deltaTime);
void endFrame(float deltaTime); KRCamera *createCamera(int width, int height);
long getCurrentFrame() const; enum {
long getLastFullyStreamedFrame() const; KRENGINE_GL_EXT_texture_storage,
float getAbsoluteTime() const; KRENGINE_NUM_EXTENSIONS
};
long getAbsoluteTimeMilliseconds();
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
std::vector<KRResource *> getResources(); static bool extension_available[KRENGINE_NUM_EXTENSIONS];
bool getStreamingEnabled();
void setStreamingEnabled(bool enable); void startFrame(float deltaTime);
void endFrame(float deltaTime);
#if TARGET_OS_IPHONE || TARGET_OS_MAC
// XXX This doesn't belong here, and might not actually be needed at all long getCurrentFrame() const;
void getMemoryStats(long &free_memory); long getLastFullyStreamedFrame() const;
#endif float getAbsoluteTime() const;
typedef enum { long getAbsoluteTimeMilliseconds();
LOG_LEVEL_INFORMATION,
LOG_LEVEL_WARNING, std::vector<KRResource *> getResources();
LOG_LEVEL_ERROR bool getStreamingEnabled();
} log_level; void setStreamingEnabled(bool enable);
typedef void log_callback(void *userdata, const std::string &message, log_level level); #if TARGET_OS_IPHONE || TARGET_OS_MAC
// XXX This doesn't belong here, and might not actually be needed at all
static void SetLogCallback(log_callback *log_callback, void *user_data); void getMemoryStats(long &free_memory);
static void Log(log_level level, const std::string message_format, ...); #endif
void doStreaming(); typedef enum {
void receivedMemoryWarning(); LOG_LEVEL_INFORMATION,
LOG_LEVEL_WARNING,
static void activateStreamerContext(); LOG_LEVEL_ERROR
static void activateRenderContext(); } log_level;
#if TARGET_OS_MAC typedef void log_callback(void *userdata, const std::string &message, log_level level);
static void attachToView(void *view);
#endif static void SetLogCallback(log_callback *log_callback, void *user_data);
static void Log(log_level level, const std::string message_format, ...);
private:
KRBundleManager *m_pBundleManager; void doStreaming();
KRSceneManager *m_pSceneManager; void receivedMemoryWarning();
KRTextureManager *m_pTextureManager;
KRMaterialManager *m_pMaterialManager; static void activateStreamerContext();
KRShaderManager *m_pShaderManager; static void activateRenderContext();
KRMeshManager *m_pMeshManager;
KRAnimationManager *m_pAnimationManager; #if TARGET_OS_MAC
KRAnimationCurveManager *m_pAnimationCurveManager; static void attachToView(void *view);
KRAudioManager *m_pSoundManager; #endif
KRUnknownManager *m_pUnknownManager;
private:
void detectExtensions(); KRBundleManager *m_pBundleManager;
bool m_bDetectedExtensions; KRSceneManager *m_pSceneManager;
KRTextureManager *m_pTextureManager;
long m_current_frame; // TODO - Does this need to be atomic? KRMaterialManager *m_pMaterialManager;
long m_last_memory_warning_frame; // TODO - Does this need to be atomic? KRPipelineManager *m_pPipelineManager;
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic? KRMeshManager *m_pMeshManager;
float m_absolute_time; KRAnimationManager *m_pAnimationManager;
KRAnimationCurveManager *m_pAnimationCurveManager;
#ifdef __APPLE__ KRAudioManager *m_pSoundManager;
mach_timebase_info_data_t m_timebase_info; KRUnknownManager *m_pUnknownManager;
#endif KRShaderManager *m_pShaderManager;
KRSourceManager *m_pSourceManager;
std::atomic<bool> m_streamingEnabled;
KRResource** m_resourceMap;
size_t m_resourceMapSize;
static log_callback *s_log_callback;
static void *s_log_callback_user_data; void detectExtensions();
bool m_bDetectedExtensions;
KRStreamer m_streamer;
long m_current_frame; // TODO - Does this need to be atomic?
static void createDeviceContexts(); long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
void destroyDeviceContexts(); long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
}; float m_absolute_time;
#endif #ifdef __APPLE__
mach_timebase_info_data_t m_timebase_info;
#endif
std::atomic<bool> m_streamingEnabled;
static log_callback *s_log_callback;
static void *s_log_callback_user_data;
KRStreamer m_streamer;
VkInstance m_vulkanInstance;
void createDeviceContexts();
void destroyDeviceContexts();
};
#endif

View File

@@ -20,7 +20,7 @@ void KRContext::destroyDeviceContexts()
gRenderContext = nil; gRenderContext = nil;
} }
void KRContext::createDeviceContexts() void createGLDeviceContexts()
{ {
if(gRenderContext == nil) { if(gRenderContext == nil) {
@@ -63,20 +63,20 @@ void KRContext::createDeviceContexts()
void KRContext::activateStreamerContext() void KRContext::activateStreamerContext()
{ {
createDeviceContexts(); createGLDeviceContexts();
[gStreamerContext makeCurrentContext]; [gStreamerContext makeCurrentContext];
} }
void KRContext::activateRenderContext() void KRContext::activateRenderContext()
{ {
createDeviceContexts(); createGLDeviceContexts();
[gRenderContext update]; [gRenderContext update];
[gRenderContext makeCurrentContext]; [gRenderContext makeCurrentContext];
} }
void KRContext::attachToView(void *view) void KRContext::attachToView(void *view)
{ {
createDeviceContexts(); createGLDeviceContexts();
NSView *v = (NSView *)view; NSView *v = (NSView *)view;
[gRenderContext setView: v]; [gRenderContext setView: v];
[gRenderContext update]; [gRenderContext update];

View File

@@ -1,207 +1,207 @@
// //
// KREngine.h // KREngine.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRDSP.h" #include "KRDSP.h"
#ifdef KRDSP_SLOW #ifdef KRDSP_SLOW
#include "KREngine-common.h" #include "KREngine-common.h"
namespace KRDSP { namespace KRDSP {
FFTWorkspace::FFTWorkspace() FFTWorkspace::FFTWorkspace()
{ {
sin_table = nullptr; sin_table = nullptr;
cos_table = nullptr; cos_table = nullptr;
} }
FFTWorkspace::~FFTWorkspace() FFTWorkspace::~FFTWorkspace()
{ {
destroy(); destroy();
} }
void FFTWorkspace::create(size_t length) void FFTWorkspace::create(size_t length)
{ {
size_t size = (length / 2); size_t size = (length / 2);
cos_table = new float[size]; cos_table = new float[size];
sin_table = new float[size]; sin_table = new float[size];
for (int i = 0; i < size / 2; i++) { for (int i = 0; i < size / 2; i++) {
float a = 2.0f * M_PI * i / length; float a = 2.0f * (float)M_PI * i / length;
cos_table[i] = cos(a); cos_table[i] = cos(a);
sin_table[i] = sin(a); sin_table[i] = sin(a);
} }
} }
void FFTWorkspace::destroy() void FFTWorkspace::destroy()
{ {
if (sin_table) { if (sin_table) {
delete sin_table; delete sin_table;
sin_table = nullptr; sin_table = nullptr;
} }
if (cos_table) { if (cos_table) {
delete cos_table; delete cos_table;
cos_table = nullptr; cos_table = nullptr;
} }
} }
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{ {
// Radix-2 Decimation in Time FFT Algorithm // Radix-2 Decimation in Time FFT Algorithm
// http://en.dsplib.org/content/fft_dec_in_time.html // http://en.dsplib.org/content/fft_dec_in_time.html
// Only power-of-two sizes supported // Only power-of-two sizes supported
assert((count & (count - 1)) == 0); assert((count & (count - 1)) == 0);
int levels = 0; unsigned int levels = 0;
while (1 << levels <= count) { while (1 << levels <= (int)count) {
levels++; levels++;
} }
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
size_t j = 0; size_t j = 0;
for (int k = 0; k < levels; k++) { for (int k = 0; k < (int)levels; k++) {
j <<= 1; j <<= 1;
j |= ((i >> k) & 1); j |= ((i >> k) & 1);
} }
if (j > i) { if (j > i) {
float temp = src->realp[i]; float temp = src->realp[i];
src->realp[i] = src->realp[j]; src->realp[i] = src->realp[j];
src->realp[j] = temp; src->realp[j] = temp;
temp = src->imagp[i]; temp = src->imagp[i];
src->imagp[i] = src->imagp[j]; src->imagp[i] = src->imagp[j];
src->imagp[j] = temp; src->imagp[j] = temp;
} }
} }
for (size_t size = 2; size <= count; size *= 2) { for (size_t size = 2; size <= count; size *= 2) {
size_t halfsize = size / 2; size_t halfsize = size / 2;
size_t step = count / size; size_t step = count / size;
for (size_t i = 0; i < count; i += size) { for (size_t i = 0; i < count; i += size) {
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) { for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k]; float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
temp_real += src->imagp[j + halfsize] * workspace.sin_table[k]; temp_real += src->imagp[j + halfsize] * workspace.sin_table[k];
float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k]; float temp_imag = -src->realp[j + halfsize] * workspace.sin_table[k];
temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k]; temp_imag += src->imagp[j + halfsize] * workspace.cos_table[k];
src->realp[j + halfsize] = src->realp[j] - temp_real; src->realp[j + halfsize] = src->realp[j] - temp_real;
src->imagp[j + halfsize] = src->imagp[j] - temp_imag; src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
src->realp[j] += temp_real; src->realp[j] += temp_real;
src->imagp[j] += temp_imag; src->imagp[j] += temp_imag;
} }
} }
} }
} }
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count) void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
{ {
SplitComplex swapped; SplitComplex swapped;
swapped.imagp = src->realp; swapped.imagp = src->realp;
swapped.realp = src->imagp; swapped.realp = src->imagp;
FFTForward(workspace, &swapped, count); FFTForward(workspace, &swapped, count);
} }
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count) void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
{ {
const short *r = src; const short *r = src;
float *w = dest; float *w = dest;
while (w < dest + destStride * count) { while (w < dest + destStride * count) {
*w = (float)*r; *w = (float)*r;
r += srcStride; r += srcStride;
w += destStride; w += destStride;
} }
} }
void Scale(float *buffer, float scale, size_t count) void Scale(float *buffer, float scale, size_t count)
{ {
float *w = buffer; float *w = buffer;
while (w < buffer + count) { while (w < buffer + count) {
*w *= scale; *w *= scale;
w++; w++;
} }
} }
void ScaleCopy(const float *src, float scale, float *dest, size_t count) void ScaleCopy(const float *src, float scale, float *dest, size_t count)
{ {
const float *r = src; const float *r = src;
float *w = dest; float *w = dest;
while (w < dest + count) { while (w < dest + count) {
*w = *r * scale; *w = *r * scale;
w++; w++;
r++; r++;
} }
} }
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count) void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
{ {
ScaleCopy(src->realp, scale, dest->realp, count); ScaleCopy(src->realp, scale, dest->realp, count);
ScaleCopy(src->imagp, scale, dest->imagp, count); ScaleCopy(src->imagp, scale, dest->imagp, count);
} }
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count) void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
{ {
float *w = buffer; float *w = buffer;
float s = scaleStart; float s = scaleStart;
while (w < buffer + count) { while (w < buffer + count) {
*w *= s; *w *= s;
w++; w++;
s += scaleStep; s += scaleStep;
} }
} }
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count) void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
{ {
float *w = buffer; float *w = buffer;
const float *r = buffer2; const float *r = buffer2;
while (w < buffer + bufferStride * count) { while (w < buffer + bufferStride * count) {
*w *= *r; *w *= *r;
w += bufferStride; w += bufferStride;
r += buffer2Stride; r += buffer2Stride;
} }
} }
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count) void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
{ {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
buffer->imagp[i] += buffer2->imagp[i]; buffer->imagp[i] += buffer2->imagp[i];
buffer->realp[i] += buffer2->realp[i]; buffer->realp[i] += buffer2->realp[i];
} }
} }
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count) void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
{ {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i]; c->realp[i] = a->realp[i] * b->realp[i] - a->imagp[i] * b->imagp[i];
c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i]; c->imagp[i] = a->realp[i] * b->imagp[i] + a->imagp[i] * b->realp[i];
} }
} }
} // namespace KRDSP } // namespace KRDSP
#endif // KRDSP_SLOW #endif // KRDSP_SLOW

View File

@@ -35,6 +35,10 @@
#include "KRContext.h" #include "KRContext.h"
#include <errno.h> #include <errno.h>
#if defined(__APPLE__) || defined(ANDROID)
#include <unistd.h>
#include <sys/mman.h>
#endif
#define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1)) #define KRAKEN_MEM_ROUND_DOWN_PAGE(x) ((x) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1))
#define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1)) + KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY) #define KRAKEN_MEM_ROUND_UP_PAGE(x) ((((x) - 1) & ~(KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY - 1)) + KRContext::KRENGINE_SYS_ALLOCATION_GRANULARITY)
@@ -91,7 +95,10 @@ void KRDataBlock::unload()
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile != INVALID_HANDLE_VALUE) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
CloseHandle(m_hPackFile); // Memory mapped file
if (m_fileOwnerDataBlock == this) {
CloseHandle(m_hPackFile);
}
m_hPackFile = INVALID_HANDLE_VALUE; m_hPackFile = INVALID_HANDLE_VALUE;
} }
#elif defined(__APPLE__) #elif defined(__APPLE__)
@@ -136,7 +143,6 @@ bool KRDataBlock::load(const std::string &path)
bool success = false; bool success = false;
unload(); unload();
struct stat statbuf;
m_bReadOnly = true; m_bReadOnly = true;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
@@ -146,7 +152,7 @@ bool KRDataBlock::load(const std::string &path)
m_fileName = KRResource::GetFileBase(path); m_fileName = KRResource::GetFileBase(path);
FILE_STANDARD_INFO fileInfo; FILE_STANDARD_INFO fileInfo;
if(GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) { if(GetFileInformationByHandleEx(m_hPackFile, FileStandardInfo, &fileInfo, sizeof(fileInfo))) {
m_data_size = fileInfo.AllocationSize.QuadPart; m_data_size = fileInfo.EndOfFile.QuadPart;
m_data_offset = 0; m_data_offset = 0;
success = true; success = true;
} }
@@ -156,6 +162,7 @@ bool KRDataBlock::load(const std::string &path)
if(m_fdPackFile >= 0) { if(m_fdPackFile >= 0) {
m_fileOwnerDataBlock = this; m_fileOwnerDataBlock = this;
m_fileName = KRResource::GetFileBase(path); m_fileName = KRResource::GetFileBase(path);
struct stat statbuf;
if(fstat(m_fdPackFile, &statbuf) >= 0) { if(fstat(m_fdPackFile, &statbuf) >= 0) {
m_data_size = statbuf.st_size; m_data_size = statbuf.st_size;
m_data_offset = 0; m_data_offset = 0;
@@ -177,9 +184,9 @@ KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
new_block->m_data_size = length; new_block->m_data_size = length;
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_hPackFile) { if(m_hPackFile != INVALID_HANDLE_VALUE) {
new_block->m_hPackFile = m_hPackFile; new_block->m_hPackFile = m_hPackFile;
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
if (m_fdPackFile) { if (m_fdPackFile) {
new_block->m_fdPackFile = m_fdPackFile; new_block->m_fdPackFile = m_fdPackFile;
#else #else
@@ -216,8 +223,8 @@ size_t KRDataBlock::getSize() const {
void KRDataBlock::expand(size_t size) void KRDataBlock::expand(size_t size)
{ {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_data == NULL && m_hPackFile == 0) { if(m_data == NULL && m_hPackFile == INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
if (m_data == NULL && m_fdPackFile == 0) { if (m_data == NULL && m_fdPackFile == 0) {
#else #else
#error Unsupported #error Unsupported
@@ -265,13 +272,13 @@ void KRDataBlock::append(void *data, size_t size) {
// Copy the entire data block to the destination pointer // Copy the entire data block to the destination pointer
void KRDataBlock::copy(void *dest) { void KRDataBlock::copy(void *dest) {
copy(dest, 0, m_data_size); copy(dest, 0, (int)m_data_size);
} }
// Copy a range of data to the destination pointer // Copy a range of data to the destination pointer
void KRDataBlock::copy(void *dest, int start, int count) { void KRDataBlock::copy(void *dest, int start, int count) {
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_lockCount == 0 && m_hPackFile != 0) { if (m_lockCount == 0 && m_hPackFile != INVALID_HANDLE_VALUE) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer // Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
LARGE_INTEGER distance; LARGE_INTEGER distance;
@@ -290,7 +297,7 @@ void KRDataBlock::copy(void *dest, int start, int count) {
bytes_remaining -= bytes_read; bytes_remaining -= bytes_read;
} }
assert(bytes_remaining == 0); assert(bytes_remaining == 0);
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
if(m_lockCount == 0 && m_fdPackFile != 0) { if(m_lockCount == 0 && m_fdPackFile != 0) {
// Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer // Optimization: If we haven't mmap'ed or malloced the data already, pread() it directly from the file into the buffer
ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset); ssize_t r = pread(m_fdPackFile, dest, count, start + m_data_offset);
@@ -365,7 +372,7 @@ bool KRDataBlock::save(const std::string& path) {
return success; return success;
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600); int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
if(fdNewFile == -1) { if(fdNewFile == -1) {
return false; return false;
@@ -410,6 +417,36 @@ std::string KRDataBlock::getString()
return ret; return ret;
} }
#if defined(_WIN32) || defined(_WIN64)
void ReportWindowsLastError(LPCTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
fprintf(stderr,
TEXT("%s failed with error %d: %s\n"),
lpszFunction, dw, lpMsgBuf);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}
#endif
// Lock the memory, forcing it to be loaded into a contiguous block of address space // Lock the memory, forcing it to be loaded into a contiguous block of address space
void KRDataBlock::lock() void KRDataBlock::lock()
{ {
@@ -417,8 +454,8 @@ void KRDataBlock::lock()
// Memory mapped file; ensure data is mapped to ram // Memory mapped file; ensure data is mapped to ram
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if(m_hFileMapping) { if(m_hPackFile != INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
if(m_fdPackFile) { if(m_fdPackFile) {
#else #else
#error Unsupported #error Unsupported
@@ -432,11 +469,17 @@ void KRDataBlock::lock()
assert(m_mmapData == NULL); assert(m_mmapData == NULL);
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_data_size, NULL); m_hFileMapping = CreateFileMappingFromApp(m_hPackFile, NULL, m_bReadOnly ? PAGE_READONLY : PAGE_READWRITE, m_data_size, NULL);
if(m_hFileMapping == NULL) {
ReportWindowsLastError("CreateFileMappingFromApp");
}
assert(m_hFileMapping != NULL); assert(m_hFileMapping != NULL);
m_mmapData = MapViewOfFileFromApp(m_hPackFile, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset); m_mmapData = MapViewOfFileFromApp(m_hFileMapping, m_bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, m_data_offset - alignment_offset, m_data_size + alignment_offset);
if(m_mmapData == NULL) {
ReportWindowsLastError("MapViewOfFileFromApp");
}
assert(m_mmapData != NULL); assert(m_mmapData != NULL);
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
//fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount); //fprintf(stderr, "KRDataBlock::lock - \"%s\" (%i)\n", m_fileOwnerDataBlock->m_fileName.c_str(), m_lockCount);
// Round m_data_offset down to the next memory page, as required by mmap // Round m_data_offset down to the next memory page, as required by mmap
@@ -495,8 +538,8 @@ void KRDataBlock::unlock()
// Memory mapped file; ensure data is unmapped from ram // Memory mapped file; ensure data is unmapped from ram
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
if (m_hPackFile) { if (m_hPackFile != INVALID_HANDLE_VALUE) {
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
if(m_fdPackFile) { if(m_fdPackFile) {
#else #else
#error Undefined #error Undefined
@@ -514,7 +557,7 @@ void KRDataBlock::unlock()
CloseHandle(m_hFileMapping); CloseHandle(m_hFileMapping);
m_hFileMapping = NULL; m_hFileMapping = NULL;
} }
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
munmap(m_mmapData, m_data_size); munmap(m_mmapData, m_data_size);
#else #else
#error Undefined #error Undefined

View File

@@ -106,7 +106,7 @@ private:
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
HANDLE m_hPackFile; HANDLE m_hPackFile;
HANDLE m_hFileMapping; HANDLE m_hFileMapping;
#elif defined(__APPLE__) #elif defined(__APPLE__) || defined(ANDROID)
int m_fdPackFile; int m_fdPackFile;
#endif #endif

View File

@@ -1,135 +1,135 @@
// //
// KRDirectionalLight.cpp // KRDirectionalLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRShader.h" #include "KRPipeline.h"
#include "KRContext.h" #include "KRContext.h"
#include "assert.h" #include "assert.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name) KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
} }
KRDirectionalLight::~KRDirectionalLight() KRDirectionalLight::~KRDirectionalLight()
{ {
} }
std::string KRDirectionalLight::getElementName() { std::string KRDirectionalLight::getElementName() {
return "directional_light"; return "directional_light";
} }
Vector3 KRDirectionalLight::getWorldLightDirection() { Vector3 KRDirectionalLight::getWorldLightDirection() {
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection()); return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
} }
Vector3 KRDirectionalLight::getLocalLightDirection() { Vector3 KRDirectionalLight::getLocalLightDirection() {
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation. return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
} }
int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) { int KRDirectionalLight::configureShadowBufferViewports(const KRViewport &viewport) {
const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame const float KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE = 1.25f; // Scale to apply to view frustrum bounds so that we don't need to refresh shadows on every frame
int cShadows = 1; int cShadows = 1;
for(int iShadow=0; iShadow < cShadows; iShadow++) { for(int iShadow=0; iShadow < cShadows; iShadow++) {
/* /*
TODO - Determine if we still need this... TODO - Determine if we still need this...
GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}}; GLfloat shadowMinDepths[3][3] = {{0.0f, 0.0f, 0.0f},{0.0f, 0.0f, 0.0f},{0.0f, 0.05f, 0.3f}};
GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}}; GLfloat shadowMaxDepths[3][3] = {{0.0f, 0.0f, 1.0f},{0.1f, 0.0f, 0.0f},{0.1f, 0.3f, 1.0f}};
float min_depth = 0.0f; float min_depth = 0.0f;
float max_depth = 1.0f; float max_depth = 1.0f;
*/ */
AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix())); AABB worldSpacefrustrumSliceBounds = AABB::Create(Vector3::Create(-1.0f, -1.0f, -1.0f), Vector3::Create(1.0f, 1.0f, 1.0f), Matrix4::Invert(viewport.getViewProjectionMatrix()));
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE); worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection()); Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0); Vector3 shadowUp = Vector3::Create(0.0, 1.0, 0.0);
if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction if(Vector3::Dot(shadowUp, shadowLook) > 0.99f) shadowUp = Vector3::Create(0.0, 0.0, 1.0); // Ensure shadow look direction is not parallel with the shadowUp direction
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp); // Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
// Matrix4 matShadowProjection = Matrix4(); // Matrix4 matShadowProjection = Matrix4();
// matShadowProjection.scale(0.001, 0.001, 0.001); // matShadowProjection.scale(0.001, 0.001, 0.001);
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp); Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
Matrix4 matShadowProjection = Matrix4(); Matrix4 matShadowProjection = Matrix4();
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection)); AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.max, Matrix4::Invert(matShadowProjection));
AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection)); AABB shadowSpaceSceneBounds = AABB::Create(getScene().getRootOctreeBounds().min, getScene().getRootOctreeBounds().max, Matrix4::Invert(matShadowProjection));
if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum if(shadowSpaceSceneBounds.min.z < shadowSpaceFrustrumSliceBounds.min.z) shadowSpaceFrustrumSliceBounds.min.z = shadowSpaceSceneBounds.min.z; // Include any potential shadow casters that are outside the view frustrum
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z); matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
Matrix4 matBias; Matrix4 matBias;
matBias.bias(); matBias.bias();
matShadowProjection *= matBias; matShadowProjection *= matBias;
KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection); KRViewport newShadowViewport = KRViewport(Vector2::Create(KRENGINE_SHADOW_MAP_WIDTH, KRENGINE_SHADOW_MAP_HEIGHT), matShadowView, matShadowProjection);
AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix())); AABB prevShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(m_shadowViewports[iShadow].getViewProjectionMatrix()));
AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix())); AABB minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE); minimumShadowBounds.scale(1.0f / KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry if(!prevShadowBounds.contains(minimumShadowBounds) || !shadowValid[iShadow] || true) { // FINDME, HACK - Re-generating the shadow map every frame. This should only be needed if the shadow contains non-static geometry
m_shadowViewports[iShadow] = newShadowViewport; m_shadowViewports[iShadow] = newShadowViewport;
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
fprintf(stderr, "Kraken - Generate shadow maps...\n"); fprintf(stderr, "Kraken - Generate shadow maps...\n");
} }
} }
return 1; return 1;
} }
void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRDirectionalLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) { if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
// Lights are rendered on the second pass of the deferred renderer // Lights are rendered on the second pass of the deferred renderer
std::vector<KRDirectionalLight *> this_light; std::vector<KRDirectionalLight *> this_light;
this_light.push_back(this); this_light.push_back(this);
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix(); Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
matModelViewInverseTranspose.transpose(); matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert(); matModelViewInverseTranspose.invert();
Vector3 light_direction_view_space = getWorldLightDirection(); Vector3 light_direction_view_space = getWorldLightDirection();
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space); light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
light_direction_view_space.normalize(); light_direction_view_space.normalize();
KRShader *pShader = getContext().getShaderManager()->getShader("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("light_directional", pCamera, std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad // Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
AABB KRDirectionalLight::getBounds() AABB KRDirectionalLight::getBounds()
{ {
return AABB::Infinite(); return AABB::Infinite();
} }

View File

@@ -47,10 +47,6 @@ using namespace kraken;
#endif #endif
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/signals2/mutex.hpp>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@@ -103,7 +99,20 @@ using std::unordered_map;
using std::unordered_multimap; using std::unordered_multimap;
using std::hash; using std::hash;
#if defined(_WIN32) || defined(_WIN64) #include <vulkan/vulkan.h>
#if defined(ANDROID)
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
// OpenGL ES 2.0 mapping to OpenGL ES 3.2
#define glDeleteQueriesEXT glDeleteQueries
#define glGenQueriesEXT glGenQueries
#define glBeginQueryEXT glBeginQuery
#define glEndQueryEXT glEndQuery
#define glGetQueryObjectuivEXT glGetQueryObjectuiv
#define glTexStorage2DEXT glTexStorage2D
#define GL_ANY_SAMPLES_PASSED_EXT GL_ANY_SAMPLES_PASSED
#define GL_QUERY_RESULT_EXT GL_QUERY_RESULT
#elif defined(_WIN32) || defined(_WIN64)
#include <mutex> #include <mutex>
#include <cstdint> #include <cstdint>

View File

@@ -732,7 +732,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setSunTemperature:(float)t -(void) setSunTemperature:(float)t
{ {
float i = [self getSunIntensity]; float i = [self getSunIntensity];
_settings.light_intensity = Vector3( _settings.light_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i, (t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i, (t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i (t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -742,7 +742,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setSunIntensity:(float)i -(void) setSunIntensity:(float)i
{ {
float t = [self getSunTemperature]; float t = [self getSunTemperature];
_settings.light_intensity = Vector3( _settings.light_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i, (t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i, (t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i (t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -778,7 +778,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setAmbientTemperature:(float)t -(void) setAmbientTemperature:(float)t
{ {
float i = [self getAmbientIntensity]; float i = [self getAmbientIntensity];
_settings.ambient_intensity = Vector3( _settings.ambient_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i, (t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i, (t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i (t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
@@ -788,7 +788,7 @@ void kraken::set_debug_text(const std::string &print_text)
-(void) setAmbientIntensity:(float)i -(void) setAmbientIntensity:(float)i
{ {
float t = [self getAmbientTemperature]; float t = [self getAmbientTemperature];
_settings.ambient_intensity = Vector3( _settings.ambient_intensity.init(
(t < 0.5f ? t * 2.0f : 1.0f) * i, (t < 0.5f ? t * 2.0f : 1.0f) * i,
(t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i, (t < 0.5f ? t * 2.0f : (1.0f - t) * 2.0f) * i,
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i (t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i

View File

@@ -4,10 +4,14 @@
#include "vector2.h" #include "vector2.h"
#include "vector3.h" #include "vector3.h"
#include "matrix4.h" #include "matrix4.h"
#include <string>
#if defined(_WIN32) || defined(_WIN64) #if defined(ANDROID)
#include <GLES3/gl3.h>
#include <GLES3/gl3ext.h>
#elif defined(_WIN32) || defined(_WIN64)
#include <glad/glad.h> #include <glad/glad.h>
#elif defined(__linux__) || defined(__unix__) || defined(__posix__) #elif (defined(__linux__) || defined(__unix__) || defined(__posix__))
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#include <GL/glext.h> #include <GL/glext.h>

View File

@@ -1,173 +1,173 @@
// //
// KRLODGroup.cpp // KRLODGroup.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRLODGroup.h" #include "KRLODGroup.h"
#include "KRLODSet.h" #include "KRLODSet.h"
#include "KRContext.h" #include "KRContext.h"
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name) KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_min_distance = 0.0f; m_min_distance = 0.0f;
m_max_distance = 0.0f; m_max_distance = 0.0f;
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero()); m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
m_use_world_units = true; m_use_world_units = true;
} }
KRLODGroup::~KRLODGroup() KRLODGroup::~KRLODGroup()
{ {
} }
std::string KRLODGroup::getElementName() { std::string KRLODGroup::getElementName() {
return "lod_group"; return "lod_group";
} }
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("min_distance", m_min_distance); e->SetAttribute("min_distance", m_min_distance);
e->SetAttribute("max_distance", m_max_distance); e->SetAttribute("max_distance", m_max_distance);
e->SetAttribute("reference_min_x", m_reference.min.x); e->SetAttribute("reference_min_x", m_reference.min.x);
e->SetAttribute("reference_min_y", m_reference.min.y); e->SetAttribute("reference_min_y", m_reference.min.y);
e->SetAttribute("reference_min_z", m_reference.min.z); e->SetAttribute("reference_min_z", m_reference.min.z);
e->SetAttribute("reference_max_x", m_reference.max.x); e->SetAttribute("reference_max_x", m_reference.max.x);
e->SetAttribute("reference_max_y", m_reference.max.y); e->SetAttribute("reference_max_y", m_reference.max.y);
e->SetAttribute("reference_max_z", m_reference.max.z); e->SetAttribute("reference_max_z", m_reference.max.z);
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false"); e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
return e; return e;
} }
void KRLODGroup::loadXML(tinyxml2::XMLElement *e) void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_min_distance = 0.0f; m_min_distance = 0.0f;
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
m_min_distance = 0.0f; m_min_distance = 0.0f;
} }
m_max_distance = 0.0f; m_max_distance = 0.0f;
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
m_max_distance = 0.0f; m_max_distance = 0.0f;
} }
float x=0.0f, y=0.0f, z=0.0f; float x=0.0f, y=0.0f, z=0.0f;
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f; x = 0.0f;
} }
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f; y = 0.0f;
} }
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f; z = 0.0f;
} }
m_reference.min = Vector3::Create(x,y,z); m_reference.min = Vector3::Create(x,y,z);
x=0.0f; y=0.0f; z=0.0f; x=0.0f; y=0.0f; z=0.0f;
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
x = 0.0f; x = 0.0f;
} }
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
y = 0.0f; y = 0.0f;
} }
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
z = 0.0f; z = 0.0f;
} }
m_reference.max = Vector3::Create(x,y,z); m_reference.max = Vector3::Create(x,y,z);
m_use_world_units = true; m_use_world_units = true;
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
m_use_world_units = true; m_use_world_units = true;
} }
} }
const AABB &KRLODGroup::getReference() const const AABB &KRLODGroup::getReference() const
{ {
return m_reference; return m_reference;
} }
void KRLODGroup::setReference(const AABB &reference) void KRLODGroup::setReference(const AABB &reference)
{ {
m_reference = reference; m_reference = reference;
} }
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport) KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
{ {
if(m_min_distance == 0 && m_max_distance == 0) { if(m_min_distance == 0 && m_max_distance == 0) {
return LOD_VISIBILITY_VISIBLE; return LOD_VISIBILITY_VISIBLE;
} else { } else {
float lod_bias = viewport.getLODBias(); float lod_bias = viewport.getLODBias();
lod_bias = pow(2.0f, -lod_bias); lod_bias = pow(2.0f, -lod_bias);
// Compare using squared distances as sqrt is expensive // Compare using squared distances as sqrt is expensive
float sqr_distance; float sqr_distance;
float sqr_prestream_distance; float sqr_prestream_distance;
Vector3 world_camera_position = viewport.getCameraPosition(); Vector3 world_camera_position = viewport.getCameraPosition();
Vector3 local_camera_position = worldToLocal(world_camera_position); Vector3 local_camera_position = worldToLocal(world_camera_position);
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position); Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
if(m_use_world_units) { if(m_use_world_units) {
Vector3 world_reference_point = localToWorld(local_reference_point); Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias); sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE; sqr_prestream_distance = (float)(getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE);
} else { } else {
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias); sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
Vector3 world_reference_point = localToWorld(local_reference_point); Vector3 world_reference_point = localToWorld(local_reference_point);
sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc? sqr_prestream_distance = worldToLocal(Vector3::Normalize(world_reference_point - world_camera_position) * (float)getContext().KRENGINE_PRESTREAM_DISTANCE).sqrMagnitude(); // TODO, FINDME - Optimize with precalc?
} }
float sqr_min_visible_distance = m_min_distance * m_min_distance; float sqr_min_visible_distance = m_min_distance * m_min_distance;
float sqr_max_visible_distance = m_max_distance * m_max_distance; float sqr_max_visible_distance = m_max_distance * m_max_distance;
if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) { if((sqr_distance >= sqr_min_visible_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_VISIBLE; return LOD_VISIBILITY_VISIBLE;
} else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) { } else if((sqr_distance >= sqr_min_visible_distance - sqr_prestream_distance || m_min_distance == 0) && (sqr_distance < sqr_max_visible_distance + sqr_prestream_distance || m_max_distance == 0)) {
return LOD_VISIBILITY_PRESTREAM; return LOD_VISIBILITY_PRESTREAM;
} else { } else {
return LOD_VISIBILITY_HIDDEN; return LOD_VISIBILITY_HIDDEN;
} }
} }
} }
float KRLODGroup::getMinDistance() float KRLODGroup::getMinDistance()
{ {
return m_min_distance; return m_min_distance;
} }
float KRLODGroup::getMaxDistance() float KRLODGroup::getMaxDistance()
{ {
return m_max_distance; return m_max_distance;
} }
void KRLODGroup::setMinDistance(float min_distance) void KRLODGroup::setMinDistance(float min_distance)
{ {
m_min_distance = min_distance; m_min_distance = min_distance;
} }
void KRLODGroup::setMaxDistance(float max_distance) void KRLODGroup::setMaxDistance(float max_distance)
{ {
m_max_distance = max_distance; m_max_distance = max_distance;
} }
void KRLODGroup::setUseWorldUnits(bool use_world_units) void KRLODGroup::setUseWorldUnits(bool use_world_units)
{ {
m_use_world_units = use_world_units; m_use_world_units = use_world_units;
} }
bool KRLODGroup::getUseWorldUnits() const bool KRLODGroup::getUseWorldUnits() const
{ {
return m_use_world_units; return m_use_world_units;
} }

View File

@@ -1,485 +1,485 @@
// //
// KRLight.cpp // KRLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRLight.h" #include "KRLight.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRShaderManager.h" #include "KRPipelineManager.h"
#include "KRShader.h" #include "KRPipeline.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
#include "KRPointLight.h" #include "KRPointLight.h"
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name) KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_intensity = 1.0f; m_intensity = 1.0f;
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
m_color = Vector3::One(); m_color = Vector3::One();
m_flareTexture = ""; m_flareTexture = "";
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
m_flareSize = 0.0f; m_flareSize = 0.0f;
m_flareOcclusionSize = 0.05f; m_flareOcclusionSize = 0.05f;
m_casts_shadow = true; m_casts_shadow = true;
m_light_shafts = true; m_light_shafts = true;
m_dust_particle_density = 0.1f; m_dust_particle_density = 0.1f;
m_dust_particle_size = 1.0f; m_dust_particle_size = 1.0f;
m_occlusionQuery = 0; m_occlusionQuery = 0;
// Initialize shadow buffers // Initialize shadow buffers
m_cShadowBuffers = 0; m_cShadowBuffers = 0;
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) { for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
shadowFramebuffer[iBuffer] = 0; shadowFramebuffer[iBuffer] = 0;
shadowDepthTexture[iBuffer] = 0; shadowDepthTexture[iBuffer] = 0;
shadowValid[iBuffer] = false; shadowValid[iBuffer] = false;
} }
} }
KRLight::~KRLight() KRLight::~KRLight()
{ {
if(m_occlusionQuery) { if(m_occlusionQuery) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
m_occlusionQuery = 0; m_occlusionQuery = 0;
} }
allocateShadowBuffers(0); allocateShadowBuffers(0);
} }
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("intensity", m_intensity); e->SetAttribute("intensity", m_intensity);
e->SetAttribute("color_r", m_color.x); e->SetAttribute("color_r", m_color.x);
e->SetAttribute("color_g", m_color.y); e->SetAttribute("color_g", m_color.y);
e->SetAttribute("color_b", m_color.z); e->SetAttribute("color_b", m_color.z);
e->SetAttribute("decay_start", m_decayStart); e->SetAttribute("decay_start", m_decayStart);
e->SetAttribute("flare_size", m_flareSize); e->SetAttribute("flare_size", m_flareSize);
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize); e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
e->SetAttribute("flare_texture", m_flareTexture.c_str()); e->SetAttribute("flare_texture", m_flareTexture.c_str());
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false"); e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false"); e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
e->SetAttribute("dust_particle_density", m_dust_particle_density); e->SetAttribute("dust_particle_density", m_dust_particle_density);
e->SetAttribute("dust_particle_size", m_dust_particle_size); e->SetAttribute("dust_particle_size", m_dust_particle_size);
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity); e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
return e; return e;
} }
void KRLight::loadXML(tinyxml2::XMLElement *e) { void KRLight::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
float x=1.0f,y=1.0f,z=1.0f; float x=1.0f,y=1.0f,z=1.0f;
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
x = 1.0; x = 1.0;
} }
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
y = 1.0; y = 1.0;
} }
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
z = 1.0; z = 1.0;
} }
m_color = Vector3::Create(x,y,z); m_color = Vector3::Create(x,y,z);
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
m_intensity = 100.0; m_intensity = 100.0;
} }
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
m_decayStart = 0.0; m_decayStart = 0.0;
} }
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
m_flareSize = 0.0; m_flareSize = 0.0;
} }
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
m_flareOcclusionSize = 0.05f; m_flareOcclusionSize = 0.05f;
} }
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
m_casts_shadow = true; m_casts_shadow = true;
} }
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) { if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
m_light_shafts = true; m_light_shafts = true;
} }
m_dust_particle_density = 0.1f; m_dust_particle_density = 0.1f;
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
m_dust_particle_density = 0.1f; m_dust_particle_density = 0.1f;
} }
m_dust_particle_size = 1.0f; m_dust_particle_size = 1.0f;
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
m_dust_particle_size = 1.0f; m_dust_particle_size = 1.0f;
} }
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
m_dust_particle_intensity = 1.0f; m_dust_particle_intensity = 1.0f;
} }
const char *szFlareTexture = e->Attribute("flare_texture"); const char *szFlareTexture = e->Attribute("flare_texture");
if(szFlareTexture) { if(szFlareTexture) {
m_flareTexture = szFlareTexture; m_flareTexture = szFlareTexture;
} else { } else {
m_flareTexture = ""; m_flareTexture = "";
} }
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
} }
void KRLight::setFlareTexture(std::string flare_texture) { void KRLight::setFlareTexture(std::string flare_texture) {
m_flareTexture = flare_texture; m_flareTexture = flare_texture;
m_pFlareTexture = NULL; m_pFlareTexture = NULL;
} }
void KRLight::setFlareSize(float flare_size) { void KRLight::setFlareSize(float flare_size) {
m_flareSize = flare_size; m_flareSize = flare_size;
} }
void KRLight::setFlareOcclusionSize(float occlusion_size) { void KRLight::setFlareOcclusionSize(float occlusion_size) {
m_flareOcclusionSize = occlusion_size; m_flareOcclusionSize = occlusion_size;
} }
void KRLight::setIntensity(float intensity) { void KRLight::setIntensity(float intensity) {
m_intensity = intensity; m_intensity = intensity;
} }
float KRLight::getIntensity() { float KRLight::getIntensity() {
return m_intensity; return m_intensity;
} }
const Vector3 &KRLight::getColor() { const Vector3 &KRLight::getColor() {
return m_color; return m_color;
} }
void KRLight::setColor(const Vector3 &color) { void KRLight::setColor(const Vector3 &color) {
m_color = color; m_color = color;
} }
void KRLight::setDecayStart(float decayStart) { void KRLight::setDecayStart(float decayStart) {
m_decayStart = decayStart; m_decayStart = decayStart;
} }
float KRLight::getDecayStart() { float KRLight::getDecayStart() {
return m_decayStart; return m_decayStart;
} }
void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) { if(renderPass == KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && (pCamera->settings.volumetric_environment_enable || pCamera->settings.dust_particle_enable || (pCamera->settings.m_cShadowBuffers > 0 && m_casts_shadow))) {
allocateShadowBuffers(configureShadowBufferViewports(viewport)); allocateShadowBuffers(configureShadowBufferViewports(viewport));
renderShadowBuffers(pCamera); renderShadowBuffers(pCamera);
} }
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
// Render brownian particles for dust floating in air // Render brownian particles for dust floating in air
if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) { if(m_cShadowBuffers >= 1 && shadowValid[0] && m_dust_particle_density > 0.0f && m_dust_particle_size > 0.0f && m_dust_particle_intensity > 0.0f) {
if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"? if(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
float particle_range = 600.0f; float particle_range = 600.0f;
int particle_count = m_dust_particle_density * pow(particle_range, 3); int particle_count = (int)(m_dust_particle_density * pow(particle_range, 3));
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES; if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
Matrix4 particleModelMatrix; Matrix4 particleModelMatrix;
particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum particleModelMatrix.scale(particle_range); // Scale the box symetrically to ensure that we don't have an uneven distribution of particles for different angles of the view frustrum
particleModelMatrix.translate(viewport.getCameraPosition()); particleModelMatrix.translate(viewport.getCameraPosition());
std::vector<KRDirectionalLight *> this_directional_light; std::vector<KRDirectionalLight *> this_directional_light;
std::vector<KRSpotLight *> this_spot_light; std::vector<KRSpotLight *> this_spot_light;
std::vector<KRPointLight *> this_point_light; std::vector<KRPointLight *> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this); KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this); KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this); KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
if(directional_light) { if(directional_light) {
this_directional_light.push_back(directional_light); this_directional_light.push_back(directional_light);
} }
if(spot_light) { if(spot_light) {
this_spot_light.push_back(spot_light); this_spot_light.push_back(spot_light);
} }
if(point_light) { if(point_light) {
this_point_light.push_back(point_light); this_point_light.push_back(point_light);
} }
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pParticleShader = m_pContext->getPipelineManager()->getPipeline("dust_particle", pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pParticleShader, viewport, particleModelMatrix, this_point_light, this_directional_light, this_spot_light, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity); pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero())); pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size); pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
KRDataBlock particle_index_data; KRDataBlock particle_index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), particle_index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
} }
} }
} }
} }
if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) { if(renderPass == KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && pCamera->settings.volumetric_environment_enable && m_light_shafts) {
std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog"; std::string shader_name = pCamera->settings.volumetric_environment_downsample != 0 ? "volumetric_fog_downsampled" : "volumetric_fog";
std::vector<KRDirectionalLight *> this_directional_light; std::vector<KRDirectionalLight *> this_directional_light;
std::vector<KRSpotLight *> this_spot_light; std::vector<KRSpotLight *> this_spot_light;
std::vector<KRPointLight *> this_point_light; std::vector<KRPointLight *> this_point_light;
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this); KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this); KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this); KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
if(directional_light) { if(directional_light) {
this_directional_light.push_back(directional_light); this_directional_light.push_back(directional_light);
} }
if(spot_light) { if(spot_light) {
this_spot_light.push_back(spot_light); this_spot_light.push_back(spot_light);
} }
if(point_light) { if(point_light) {
this_point_light.push_back(point_light); this_point_light.push_back(point_light);
} }
KRShader *pFogShader = m_pContext->getShaderManager()->getShader(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES); KRPipeline *pFogShader = m_pContext->getPipelineManager()->getPipeline(shader_name, pCamera, this_point_light, this_directional_light, this_spot_light, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_ADDITIVE_PARTICLES);
if(getContext().getShaderManager()->selectShader(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pFogShader, viewport, Matrix4(), this_point_light, this_directional_light, this_spot_light, 0, KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE, Vector3::Zero(), 0.0f, Vector4::Zero())) {
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5; int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
float slice_near = -pCamera->settings.getPerspectiveNearZ(); float slice_near = -pCamera->settings.getPerspectiveNearZ();
float slice_far = -pCamera->settings.volumetric_environment_max_distance; float slice_far = -pCamera->settings.volumetric_environment_max_distance;
float slice_spacing = (slice_far - slice_near) / slice_count; float slice_spacing = (slice_far - slice_near) / slice_count;
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing)); pFogShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing));
pFogShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f)); pFogShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
KRDataBlock index_data; KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getVolumetricLightingVertexes(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX), true, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, slice_count*6));
} }
} }
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) { if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
if(m_flareTexture.size() && m_flareSize > 0.0f) { if(m_flareTexture.size() && m_flareSize > 0.0f) {
Matrix4 occlusion_test_sphere_matrix = Matrix4(); Matrix4 occlusion_test_sphere_matrix = Matrix4();
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize); occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
occlusion_test_sphere_matrix.translate(m_localTranslation); occlusion_test_sphere_matrix.translate(m_localTranslation);
if(m_parentNode) { if(m_parentNode) {
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix(); occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
} }
if(getContext().getShaderManager()->selectShader("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline("occlusion_test", *pCamera, point_lights, directional_lights, spot_lights, 0, viewport, occlusion_test_sphere_matrix, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
#else #else
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery)); GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
#endif #endif
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
} }
} }
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT)); GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#else #else
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED)); GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
#endif #endif
} }
} }
} }
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_flareTexture.size() && m_flareSize > 0.0f) { if(m_flareTexture.size() && m_flareSize > 0.0f) {
if(m_occlusionQuery) { if(m_occlusionQuery) {
GLuint params = 0; GLuint params = 0;
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params)); GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, &params));
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
if(params) { if(params) {
if(!m_pFlareTexture && m_flareTexture.size()) { if(!m_pFlareTexture && m_flareTexture.size()) {
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture); m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
} }
if(m_pFlareTexture) { if(m_pFlareTexture) {
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light flare on transparency pass // Render light flare on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("flare", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE); m_pContext->getTextureManager()->selectTexture(0, m_pFlareTexture, 0.0f, KRTexture::TEXTURE_USAGE_LIGHT_FLARE);
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
} }
} }
} }
} }
void KRLight::allocateShadowBuffers(int cBuffers) { void KRLight::allocateShadowBuffers(int cBuffers) {
// First deallocate buffers no longer needed // First deallocate buffers no longer needed
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) { for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
if (shadowDepthTexture[iShadow]) { if (shadowDepthTexture[iShadow]) {
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
shadowDepthTexture[iShadow] = 0; shadowDepthTexture[iShadow] = 0;
} }
if (shadowFramebuffer[iShadow]) { if (shadowFramebuffer[iShadow]) {
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
shadowFramebuffer[iShadow] = 0; shadowFramebuffer[iShadow] = 0;
} }
} }
// Allocate newly required buffers // Allocate newly required buffers
for(int iShadow = 0; iShadow < cBuffers; iShadow++) { for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
Vector2 viewportSize = m_shadowViewports[iShadow].getSize(); Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
if(!shadowDepthTexture[iShadow]) { if(!shadowDepthTexture[iShadow]) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow)); GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow)); GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
// ===== Create offscreen shadow framebuffer object ===== // ===== Create offscreen shadow framebuffer object =====
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
// ----- Create Depth Texture for shadowFramebuffer ----- // ----- Create Depth Texture for shadowFramebuffer -----
GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow])); GLDEBUG( glBindTexture(GL_TEXTURE_2D, shadowDepthTexture[iShadow]));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE); m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
#if GL_EXT_shadow_samplers #if GL_EXT_shadow_samplers
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_EXT, GL_COMPARE_REF_TO_TEXTURE_EXT)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
#endif #endif
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL)); GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, (GLsizei)viewportSize.x, (GLsizei)viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
} }
} }
m_cShadowBuffers = cBuffers; m_cShadowBuffers = cBuffers;
} }
void KRLight::deleteBuffers() void KRLight::deleteBuffers()
{ {
// Called when this light wasn't used in the last frame, so we can free the resources for use by other lights // Called when this light wasn't used in the last frame, so we can free the resources for use by other lights
allocateShadowBuffers(0); allocateShadowBuffers(0);
} }
void KRLight::invalidateShadowBuffers() void KRLight::invalidateShadowBuffers()
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
shadowValid[iShadow] = false; shadowValid[iShadow] = false;
} }
} }
int KRLight::configureShadowBufferViewports(const KRViewport &viewport) int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
{ {
return 0; return 0;
} }
void KRLight::renderShadowBuffers(KRCamera *pCamera) void KRLight::renderShadowBuffers(KRCamera *pCamera)
{ {
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) { for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
if(!shadowValid[iShadow]) { if(!shadowValid[iShadow]) {
shadowValid[iShadow] = true; shadowValid[iShadow] = true;
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow])); GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0)); GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
GLDEBUG(glViewport(0, 0, m_shadowViewports[iShadow].getSize().x, m_shadowViewports[iShadow].getSize().y)); GLDEBUG(glViewport(0, 0, (GLsizei)m_shadowViewports[iShadow].getSize().x, (GLsizei)m_shadowViewports[iShadow].getSize().y));
GLDEBUG(glClearDepthf(0.0f)); GLDEBUG(glClearDepthf(0.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2)); GLDEBUG(glViewport(1, 1, (GLsizei)m_shadowViewports[iShadow].getSize().x - 2, (GLsizei)m_shadowViewports[iShadow].getSize().y - 2));
GLDEBUG(glClearDepthf(1.0f)); GLDEBUG(glClearDepthf(1.0f));
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT)); GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
GLDEBUG(glDisable(GL_DITHER)); GLDEBUG(glDisable(GL_DITHER));
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts //GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
//GLDEBUG(glEnable(GL_CULL_FACE)); //GLDEBUG(glEnable(GL_CULL_FACE));
GLDEBUG(glDisable(GL_CULL_FACE)); GLDEBUG(glDisable(GL_CULL_FACE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LESS)); GLDEBUG(glDepthFunc(GL_LESS));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Disable alpha blending as we are using alpha channel for packed depth info // Disable alpha blending as we are using alpha channel for packed depth info
GLDEBUG(glDisable(GL_BLEND)); GLDEBUG(glDisable(GL_BLEND));
// Use shader program // Use shader program
KRShader *shadowShader = m_pContext->getShaderManager()->getShader("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT); KRPipeline *shadowShader = m_pContext->getPipelineManager()->getPipeline("ShadowShader", pCamera, std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, KRNode::RENDER_PASS_FORWARD_TRANSPARENT);
getContext().getShaderManager()->selectShader(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero()); getContext().getPipelineManager()->selectPipeline(*pCamera, shadowShader, m_shadowViewports[iShadow], Matrix4(), std::vector<KRPointLight *>(), std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, KRNode::RENDER_PASS_SHADOWMAP, Vector3::Zero(), 0.0f, Vector4::Zero());
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true); getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
GLDEBUG(glEnable(GL_CULL_FACE)); GLDEBUG(glEnable(GL_CULL_FACE));
} }
} }
} }
int KRLight::getShadowBufferCount() int KRLight::getShadowBufferCount()
{ {
int cBuffers=0; int cBuffers=0;
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) { for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
if(shadowValid[iBuffer]) { if(shadowValid[iBuffer]) {
cBuffers++; cBuffers++;
} else { } else {
break; break;
} }
} }
return cBuffers; return cBuffers;
} }
GLuint *KRLight::getShadowTextures() GLuint *KRLight::getShadowTextures()
{ {
return shadowDepthTexture; return shadowDepthTexture;
} }
KRViewport *KRLight::getShadowViewports() KRViewport *KRLight::getShadowViewports()
{ {
return m_shadowViewports; return m_shadowViewports;
} }

View File

@@ -34,7 +34,22 @@ void KRLocator::loadXML(tinyxml2::XMLElement *e)
KRNode::loadXML(e); KRNode::loadXML(e);
} }
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &KRLocator::getUserAttributes() unordered_map<std::string, int> &KRLocator::getUserIntAttributes()
{ {
return m_userAttributes; return m_userIntAttributes;
} }
unordered_map<std::string, double> &KRLocator::getUserDoubleAttributes()
{
return m_userDoubleAttributes;
}
unordered_map<std::string, bool> &KRLocator::getUserBoolAttributes()
{
return m_userBoolAttributes;
}
unordered_map<std::string, std::string> &KRLocator::getUserStringAttributes()
{
return m_userStringAttributes;
}

View File

@@ -13,8 +13,6 @@
#include "KRNode.h" #include "KRNode.h"
#include "KRTexture.h" #include "KRTexture.h"
#include "boost/variant.hpp"
class KRLocator : public KRNode { class KRLocator : public KRNode {
public: public:
KRLocator(KRScene &scene, std::string name); KRLocator(KRScene &scene, std::string name);
@@ -22,10 +20,16 @@ public:
virtual std::string getElementName(); virtual std::string getElementName();
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent); virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
virtual void loadXML(tinyxml2::XMLElement *e); virtual void loadXML(tinyxml2::XMLElement *e);
unordered_map<std::string, boost::variant<int, double, bool, std::string> > &getUserAttributes(); unordered_map<std::string, int> &getUserIntAttributes();
unordered_map<std::string, double> &getUserDoubleAttributes();
unordered_map<std::string, bool> &getUserBoolAttributes();
unordered_map<std::string, std::string> &getUserStringAttributes();
private: private:
unordered_map<std::string, boost::variant<int, double, bool, std::string> > m_userAttributes; unordered_map<std::string, int> m_userIntAttributes;
unordered_map<std::string, double> m_userDoubleAttributes;
unordered_map<std::string, bool> m_userBoolAttributes;
unordered_map<std::string, std::string> m_userStringAttributes;
}; };

View File

@@ -1,422 +1,422 @@
// //
// KRMaterial.cpp // KRMaterial.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRMaterial.h" #include "KRMaterial.h"
#include "KRTextureManager.h" #include "KRTextureManager.h"
#include "KRContext.h" #include "KRContext.h"
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) { KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
m_name = szName; m_name = szName;
m_pAmbientMap = NULL; m_pAmbientMap = NULL;
m_pDiffuseMap = NULL; m_pDiffuseMap = NULL;
m_pSpecularMap = NULL; m_pSpecularMap = NULL;
m_pNormalMap = NULL; m_pNormalMap = NULL;
m_pReflectionMap = NULL; m_pReflectionMap = NULL;
m_pReflectionCube = NULL; m_pReflectionCube = NULL;
m_ambientColor = Vector3::Zero(); m_ambientColor = Vector3::Zero();
m_diffuseColor = Vector3::One(); m_diffuseColor = Vector3::One();
m_specularColor = Vector3::One(); m_specularColor = Vector3::One();
m_reflectionColor = Vector3::Zero(); m_reflectionColor = Vector3::Zero();
m_tr = (GLfloat)1.0f; m_tr = (GLfloat)1.0f;
m_ns = (GLfloat)0.0f; m_ns = (GLfloat)0.0f;
m_ambientMap = ""; m_ambientMap = "";
m_diffuseMap = ""; m_diffuseMap = "";
m_specularMap = ""; m_specularMap = "";
m_normalMap = ""; m_normalMap = "";
m_reflectionMap = ""; m_reflectionMap = "";
m_reflectionCube = ""; m_reflectionCube = "";
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f); m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
m_specularMapOffset = Vector2::Create(0.0f, 0.0f); m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f); m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
m_ambientMapScale = Vector2::Create(1.0f, 1.0f); m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
m_specularMapScale = Vector2::Create(1.0f, 1.0f); m_specularMapScale = Vector2::Create(1.0f, 1.0f);
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f); m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f); m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f); m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE; m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
} }
KRMaterial::~KRMaterial() { KRMaterial::~KRMaterial() {
} }
std::string KRMaterial::getExtension() { std::string KRMaterial::getExtension() {
return "mtl"; return "mtl";
} }
bool KRMaterial::needsVertexTangents() bool KRMaterial::needsVertexTangents()
{ {
return m_normalMap.size() > 0; return m_normalMap.size() > 0;
} }
bool KRMaterial::save(KRDataBlock &data) { bool KRMaterial::save(KRDataBlock &data) {
std::stringstream stream; std::stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10); stream.precision(std::numeric_limits<long double>::digits10);
stream.setf(std::ios::fixed,std::ios::floatfield); stream.setf(std::ios::fixed,std::ios::floatfield);
stream << "newmtl " << m_name; stream << "newmtl " << m_name;
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z; stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z; stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z; stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z; stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
stream << "\nTr " << m_tr; stream << "\nTr " << m_tr;
stream << "\nNs " << m_ns; stream << "\nNs " << m_ns;
if(m_ambientMap.size()) { if(m_ambientMap.size()) {
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y; stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
} else { } else {
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_diffuseMap.size()) { if(m_diffuseMap.size()) {
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y; stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
} else { } else {
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_specularMap.size()) { if(m_specularMap.size()) {
stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n"; stream << "\nmap_Ks " << m_specularMap << ".pvr -s " << m_specularMapScale.x << " " << m_specularMapScale.y << " -o " << m_specularMapOffset.x << " " << m_specularMapOffset.y << "\n";
} else { } else {
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_normalMap.size()) { if(m_normalMap.size()) {
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y; stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
} else { } else {
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_reflectionMap.size()) { if(m_reflectionMap.size()) {
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y; stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
} else { } else {
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0"; stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
} }
if(m_reflectionCube.size()) { if(m_reflectionCube.size()) {
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr"; stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
} else { } else {
stream << "\n# map_ReflectionCube cubemapname"; stream << "\n# map_ReflectionCube cubemapname";
} }
switch(m_alpha_mode) { switch(m_alpha_mode) {
case KRMATERIAL_ALPHA_MODE_OPAQUE: case KRMATERIAL_ALPHA_MODE_OPAQUE:
stream << "\nalpha_mode opaque"; stream << "\nalpha_mode opaque";
break; break;
case KRMATERIAL_ALPHA_MODE_TEST: case KRMATERIAL_ALPHA_MODE_TEST:
stream << "\nalpha_mode test"; stream << "\nalpha_mode test";
break; break;
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE: case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
stream << "\nalpha_mode blendoneside"; stream << "\nalpha_mode blendoneside";
break; break;
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE: case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
stream << "\nalpha_mode blendtwoside"; stream << "\nalpha_mode blendtwoside";
break; break;
} }
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside"; stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
stream << "\n"; stream << "\n";
data.append(stream.str()); data.append(stream.str());
return true; return true;
} }
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_ambientMap = texture_name; m_ambientMap = texture_name;
m_ambientMapScale = texture_scale; m_ambientMapScale = texture_scale;
m_ambientMapOffset = texture_offset; m_ambientMapOffset = texture_offset;
} }
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_diffuseMap = texture_name; m_diffuseMap = texture_name;
m_diffuseMapScale = texture_scale; m_diffuseMapScale = texture_scale;
m_diffuseMapOffset = texture_offset; m_diffuseMapOffset = texture_offset;
} }
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_specularMap = texture_name; m_specularMap = texture_name;
m_specularMapScale = texture_scale; m_specularMapScale = texture_scale;
m_specularMapOffset = texture_offset; m_specularMapOffset = texture_offset;
} }
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_normalMap = texture_name; m_normalMap = texture_name;
m_normalMapScale = texture_scale; m_normalMapScale = texture_scale;
m_normalMapOffset = texture_offset; m_normalMapOffset = texture_offset;
} }
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) { void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
m_reflectionMap = texture_name; m_reflectionMap = texture_name;
m_reflectionMapScale = texture_scale; m_reflectionMapScale = texture_scale;
m_reflectionMapOffset = texture_offset; m_reflectionMapOffset = texture_offset;
} }
void KRMaterial::setReflectionCube(std::string texture_name) { void KRMaterial::setReflectionCube(std::string texture_name) {
m_reflectionCube = texture_name; m_reflectionCube = texture_name;
} }
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) { void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
m_alpha_mode = alpha_mode; m_alpha_mode = alpha_mode;
} }
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() { KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
return m_alpha_mode; return m_alpha_mode;
} }
void KRMaterial::setAmbient(const Vector3 &c) { void KRMaterial::setAmbient(const Vector3 &c) {
m_ambientColor = c; m_ambientColor = c;
} }
void KRMaterial::setDiffuse(const Vector3 &c) { void KRMaterial::setDiffuse(const Vector3 &c) {
m_diffuseColor = c; m_diffuseColor = c;
} }
void KRMaterial::setSpecular(const Vector3 &c) { void KRMaterial::setSpecular(const Vector3 &c) {
m_specularColor = c; m_specularColor = c;
} }
void KRMaterial::setReflection(const Vector3 &c) { void KRMaterial::setReflection(const Vector3 &c) {
m_reflectionColor = c; m_reflectionColor = c;
} }
void KRMaterial::setTransparency(GLfloat a) { void KRMaterial::setTransparency(GLfloat a) {
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) { if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE); setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} }
m_tr = a; m_tr = a;
} }
void KRMaterial::setShininess(GLfloat s) { void KRMaterial::setShininess(GLfloat s) {
m_ns = s; m_ns = s;
} }
bool KRMaterial::isTransparent() { bool KRMaterial::isTransparent() {
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE; return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
} }
void KRMaterial::preStream(float lodCoverage) void KRMaterial::preStream(float lodCoverage)
{ {
getTextures(); getTextures();
if(m_pAmbientMap) { if(m_pAmbientMap) {
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP); m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
} }
if(m_pDiffuseMap) { if(m_pDiffuseMap) {
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
} }
if(m_pNormalMap) { if(m_pNormalMap) {
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
} }
if(m_pSpecularMap) { if(m_pSpecularMap) {
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
} }
if(m_pReflectionMap) { if(m_pReflectionMap) {
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP); m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
} }
if(m_pReflectionCube) { if(m_pReflectionCube) {
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
} }
} }
kraken_stream_level KRMaterial::getStreamLevel() kraken_stream_level KRMaterial::getStreamLevel()
{ {
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ; kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
getTextures(); getTextures();
if(m_pAmbientMap) { if(m_pAmbientMap) {
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP)); stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
} }
if(m_pDiffuseMap) { if(m_pDiffuseMap) {
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP)); stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
} }
if(m_pNormalMap) { if(m_pNormalMap) {
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP)); stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
} }
if(m_pSpecularMap) { if(m_pSpecularMap) {
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP)); stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
} }
if(m_pReflectionMap) { if(m_pReflectionMap) {
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP)); stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
} }
if(m_pReflectionCube) { if(m_pReflectionCube) {
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE)); stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
} }
return stream_level; return stream_level;
} }
void KRMaterial::getTextures() void KRMaterial::getTextures()
{ {
if(!m_pAmbientMap && m_ambientMap.size()) { if(!m_pAmbientMap && m_ambientMap.size()) {
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap); m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
} }
if(!m_pDiffuseMap && m_diffuseMap.size()) { if(!m_pDiffuseMap && m_diffuseMap.size()) {
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap); m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
} }
if(!m_pNormalMap && m_normalMap.size()) { if(!m_pNormalMap && m_normalMap.size()) {
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap); m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
} }
if(!m_pSpecularMap && m_specularMap.size()) { if(!m_pSpecularMap && m_specularMap.size()) {
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap); m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
} }
if(!m_pReflectionMap && m_reflectionMap.size()) { if(!m_pReflectionMap && m_reflectionMap.size()) {
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap); m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
} }
if(!m_pReflectionCube && m_reflectionCube.size()) { if(!m_pReflectionCube && m_reflectionCube.size()) {
m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str()); m_pReflectionCube = getContext().getTextureManager()->getTextureCube(m_reflectionCube.c_str());
} }
} }
bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) { bool KRMaterial::bind(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const std::vector<KRBone *> &bones, const std::vector<Matrix4> &bind_poses, const KRViewport &viewport, const Matrix4 &matModel, KRTexture *pLightMap, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, float lod_coverage) {
bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap; bool bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
getTextures(); getTextures();
Vector2 default_scale = Vector2::One(); Vector2 default_scale = Vector2::One();
Vector2 default_offset = Vector2::Zero(); Vector2 default_offset = Vector2::Zero();
bool bHasReflection = m_reflectionColor != Vector3::Zero(); bool bHasReflection = m_reflectionColor != Vector3::Zero();
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap; bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap; bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap; bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection; bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection; bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap; bool bAlphaTest = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_TEST) && bDiffuseMap;
bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE); bool bAlphaBlend = (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE) || (m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
KRShader *pShader = getContext().getShaderManager()->getShader("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("ObjectShader", pCamera, point_lights, directional_lights, spot_lights, (int)bones.size(), bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, m_diffuseMapScale != default_scale && bDiffuseMap, m_specularMapScale != default_scale && bSpecMap, m_normalMapScale != default_scale && bNormalMap, m_reflectionMapScale != default_scale && bReflectionMap, m_diffuseMapOffset != default_offset && bDiffuseMap, m_specularMapOffset != default_offset && bSpecMap, m_normalMapOffset != default_offset && bNormalMap, m_reflectionMapOffset != default_offset && bReflectionMap, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
Vector4 fade_color; Vector4 fade_color;
if(!getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) { if(!getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
return false; return false;
} }
// Bind bones // Bind bones
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) { if(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
GLfloat bone_mats[256 * 16]; GLfloat bone_mats[256 * 16];
GLfloat *bone_mat_component = bone_mats; GLfloat *bone_mat_component = bone_mats;
for(int bone_index=0; bone_index < bones.size(); bone_index++) { for(int bone_index=0; bone_index < bones.size(); bone_index++) {
KRBone *bone = bones[bone_index]; KRBone *bone = bones[bone_index];
// Vector3 initialRotation = bone->getInitialLocalRotation(); // Vector3 initialRotation = bone->getInitialLocalRotation();
// Vector3 rotation = bone->getLocalRotation(); // Vector3 rotation = bone->getLocalRotation();
// Vector3 initialTranslation = bone->getInitialLocalTranslation(); // Vector3 initialTranslation = bone->getInitialLocalTranslation();
// Vector3 translation = bone->getLocalTranslation(); // Vector3 translation = bone->getLocalTranslation();
// Vector3 initialScale = bone->getInitialLocalScale(); // Vector3 initialScale = bone->getInitialLocalScale();
// Vector3 scale = bone->getLocalScale(); // Vector3 scale = bone->getLocalScale();
// //
//printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI); //printf("%s - delta rotation: %.4f %.4f %.4f\n", bone->getName().c_str(), (rotation.x - initialRotation.x) * 180.0 / M_PI, (rotation.y - initialRotation.y) * 180.0 / M_PI, (rotation.z - initialRotation.z) * 180.0 / M_PI);
//printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z); //printf("%s - delta translation: %.4f %.4f %.4f\n", bone->getName().c_str(), translation.x - initialTranslation.x, translation.y - initialTranslation.y, translation.z - initialTranslation.z);
// printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z); // printf("%s - delta scale: %.4f %.4f %.4f\n", bone->getName().c_str(), scale.x - initialScale.x, scale.y - initialScale.y, scale.z - initialScale.z);
Matrix4 skin_bone_bind_pose = bind_poses[bone_index]; Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
Matrix4 active_mat = bone->getActivePoseMatrix(); Matrix4 active_mat = bone->getActivePoseMatrix();
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix(); Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]); Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
Matrix4 t = (inv_bind_mat * active_mat); Matrix4 t = (inv_bind_mat * active_mat);
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix(); Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
for(int i=0; i < 16; i++) { for(int i=0; i < 16; i++) {
*bone_mat_component++ = t[i]; *bone_mat_component++ = t[i];
} }
} }
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) { if(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats); glUniformMatrix4fv(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS], (GLsizei)bones.size(), GL_FALSE, bone_mats);
} }
} }
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) { if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer // We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3::Create(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z)); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, Vector3::Create(m_diffuseColor.x * pCamera->settings.light_intensity.x, m_diffuseColor.y * pCamera->settings.light_intensity.y, m_diffuseColor.z * pCamera->settings.light_intensity.z));
} else { } else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
} }
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) { if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
// We pre-multiply the light color with the material color in the forward renderer // We pre-multiply the light color with the material color in the forward renderer
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3::Create(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z)); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_SPECULAR, Vector3::Create(m_specularColor.x * pCamera->settings.light_intensity.x, m_specularColor.y * pCamera->settings.light_intensity.y, m_specularColor.z * pCamera->settings.light_intensity.z));
} else { } else {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
} }
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
if(bDiffuseMap) { if(bDiffuseMap) {
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP); m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
} }
if(bSpecMap) { if(bSpecMap) {
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP); m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
} }
if(bNormalMap) { if(bNormalMap) {
m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP); m_pContext->getTextureManager()->selectTexture(2, m_pNormalMap, lod_coverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
} }
if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { if(bReflectionCubeMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE); m_pContext->getTextureManager()->selectTexture(4, m_pReflectionCube, lod_coverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
} }
if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) { if(bReflectionMap && (renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE || renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT || renderPass == KRNode::RENDER_PASS_DEFERRED_OPAQUE)) {
// GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering // GL_TEXTURE7 is used for reading the depth buffer in gBuffer pass 2 and re-used for the reflection map in gBuffer Pass 3 and in forward rendering
m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP); m_pContext->getTextureManager()->selectTexture(7, m_pReflectionMap, lod_coverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
} }
return true; return true;
} }
const std::string &KRMaterial::getName() const const std::string &KRMaterial::getName() const
{ {
return m_name; return m_name;
} }

View File

@@ -32,8 +32,8 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRTexture.h" #include "KRTexture.h"
#include "KRShaderManager.h" #include "KRPipelineManager.h"
#include "KRShader.h" #include "KRPipeline.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRResource.h" #include "KRResource.h"
#include "KRScene.h" #include "KRScene.h"

View File

@@ -1,288 +1,306 @@
// //
// KRMaterialManager.cpp // KRMaterialManager.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRMaterialManager.h" #include "KRMaterialManager.h"
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context) KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager) : KRResourceManager(context)
{ {
m_pTextureManager = pTextureManager; m_pTextureManager = pTextureManager;
m_pShaderManager = pShaderManager; m_pPipelineManager = pPipelineManager;
} }
KRMaterialManager::~KRMaterialManager() { KRMaterialManager::~KRMaterialManager() {
} }
KRResource* KRMaterialManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials() {
{ if (extension.compare("mtl") == 0) {
return m_materials; return load(name.c_str(), data);
} }
return nullptr;
void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) { }
if(blend_enable) {
GLDEBUG(glEnable(GL_BLEND)); KRResource* KRMaterialManager::getResource(const std::string& name, const std::string& extension)
GLDEBUG(glBlendFunc(blend_src, blend_dest)); {
} else { if (extension.compare("mtl") == 0) {
GLDEBUG(glDisable(GL_BLEND)); // TODO - This is not correct -- there are multiple materials emitted in a single mtl file.
} // We should treat "mtl" files as source files, managed by KRSource, which output
// material resources when compiled.
if(depth_test_enable) { return m_materials[name];
GLDEBUG(glEnable(GL_DEPTH_TEST)); }
GLDEBUG(glDepthFunc(depth_func)); return nullptr;
} else { }
GLDEBUG(glDisable(GL_DEPTH_TEST));
} unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
{
if(depth_write_enable) { return m_materials;
GLDEBUG(glDepthMask(GL_TRUE)); }
} else {
GLDEBUG(glDepthMask(GL_FALSE)); void KRMaterialManager::configure(bool blend_enable, GLenum blend_src, GLenum blend_dest, bool depth_test_enable, GLenum depth_func, bool depth_write_enable) {
} if(blend_enable) {
} GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(blend_src, blend_dest));
} else {
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) { GLDEBUG(glDisable(GL_BLEND));
std::string lowerName = name; }
std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower); if(depth_test_enable) {
GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(depth_func));
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName); } else {
if(itr == m_materials.end()) { GLDEBUG(glDisable(GL_DEPTH_TEST));
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str()); }
// Not found
return NULL; if(depth_write_enable) {
} else { GLDEBUG(glDepthMask(GL_TRUE));
return (*itr).second; } else {
} GLDEBUG(glDepthMask(GL_FALSE));
} }
}
void KRMaterialManager::add(KRMaterial *new_material) {
// FINDME, TODO - Potential memory leak if multiple materials with the same name are added
std::string lowerName = new_material->getName(); KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
std::transform(lowerName.begin(), lowerName.end(), std::string lowerName = name;
lowerName.begin(), ::tolower); std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
m_materials[lowerName] = new_material;
}
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) { if(itr == m_materials.end()) {
KRMaterial *pMaterial = NULL; KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
char szSymbol[16][256]; // Not found
data->lock(); return NULL;
} else {
char *pScan = (char *)data->getStart(); return (*itr).second;
char *pEnd = (char *)data->getEnd(); }
while(pScan < pEnd) { }
// Scan through whitespace void KRMaterialManager::add(KRMaterial *new_material) {
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) { // FINDME, TODO - Potential memory leak if multiple materials with the same name are added
pScan++; std::string lowerName = new_material->getName();
} std::transform(lowerName.begin(), lowerName.end(),
lowerName.begin(), ::tolower);
if(*pScan == '#') {
// Line is a comment line m_materials[lowerName] = new_material;
}
// Scan to the end of the line
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { KRMaterial* KRMaterialManager::load(const char *szName, KRDataBlock *data) {
pScan++; KRMaterial *pMaterial = NULL;
} char szSymbol[16][256];
} else { data->lock();
int cSymbols = 0;
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { char *pScan = (char *)data->getStart();
char *pEnd = (char *)data->getEnd();
char *pDest = szSymbol[cSymbols++]; while(pScan < pEnd) {
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
if(*pScan >= 'A' && *pScan <= 'Z') { // Scan through whitespace
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
} else { pScan++;
*pDest++ = *pScan++; }
}
} if(*pScan == '#') {
*pDest = '\0'; // Line is a comment line
// Scan through whitespace, but don't advance to next line // Scan to the end of the line
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++; pScan++;
} }
} } else {
int cSymbols = 0;
if(cSymbols > 0) { while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) { char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]); if(*pScan >= 'A' && *pScan <= 'Z') {
m_materials[szSymbol[1]] = pMaterial; *pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
} } else {
if(pMaterial != NULL) { *pDest++ = *pScan++;
if(strcmp(szSymbol[0], "alpha_mode") == 0) { }
if(cSymbols == 2) { }
if(strcmp(szSymbol[1], "test") == 0) { *pDest = '\0';
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
} else if(strcmp(szSymbol[1], "blendoneside") == 0) { // Scan through whitespace, but don't advance to next line
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE); while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) { pScan++;
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE); }
} else { }
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
} if(cSymbols > 0) {
}
} else if(strcmp(szSymbol[0], "ka") == 0) { if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
char *pScan2 = szSymbol[1];
float r = strtof(pScan2, &pScan2); pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
if(cSymbols == 2) { m_materials[szSymbol[1]] = pMaterial;
pMaterial->setAmbient(Vector3::Create(r, r, r)); }
} else if(cSymbols == 4) { if(pMaterial != NULL) {
pScan2 = szSymbol[2]; if(strcmp(szSymbol[0], "alpha_mode") == 0) {
float g = strtof(pScan2, &pScan2); if(cSymbols == 2) {
pScan2 = szSymbol[3]; if(strcmp(szSymbol[1], "test") == 0) {
float b = strtof(pScan2, &pScan2); pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
pMaterial->setAmbient(Vector3::Create(r, g, b)); } else if(strcmp(szSymbol[1], "blendoneside") == 0) {
} pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
} else if(strcmp(szSymbol[0], "kd") == 0) { } else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
char *pScan2 = szSymbol[1]; pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
float r = strtof(pScan2, &pScan2); } else {
if(cSymbols == 2) { pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
pMaterial->setDiffuse(Vector3::Create(r, r, r)); }
} else if(cSymbols == 4) { }
pScan2 = szSymbol[2]; } else if(strcmp(szSymbol[0], "ka") == 0) {
float g = strtof(pScan2, &pScan2); char *pScan2 = szSymbol[1];
pScan2 = szSymbol[3]; float r = strtof(pScan2, &pScan2);
float b = strtof(pScan2, &pScan2); if(cSymbols == 2) {
pMaterial->setDiffuse(Vector3::Create(r, g, b)); pMaterial->setAmbient(Vector3::Create(r, r, r));
} } else if(cSymbols == 4) {
} else if(strcmp(szSymbol[0], "ks") == 0) { pScan2 = szSymbol[2];
char *pScan2 = szSymbol[1]; float g = strtof(pScan2, &pScan2);
float r = strtof(pScan2, &pScan2); pScan2 = szSymbol[3];
if(cSymbols == 2) { float b = strtof(pScan2, &pScan2);
pMaterial->setSpecular(Vector3::Create(r, r, r)); pMaterial->setAmbient(Vector3::Create(r, g, b));
} else if(cSymbols == 4) { }
pScan2 = szSymbol[2]; } else if(strcmp(szSymbol[0], "kd") == 0) {
float g = strtof(pScan2, &pScan2); char *pScan2 = szSymbol[1];
pScan2 = szSymbol[3]; float r = strtof(pScan2, &pScan2);
float b = strtof(pScan2, &pScan2); if(cSymbols == 2) {
pMaterial->setSpecular(Vector3::Create(r, g, b)); pMaterial->setDiffuse(Vector3::Create(r, r, r));
} } else if(cSymbols == 4) {
} else if(strcmp(szSymbol[0], "kr") == 0) { pScan2 = szSymbol[2];
char *pScan2 = szSymbol[1]; float g = strtof(pScan2, &pScan2);
float r = strtof(pScan2, &pScan2); pScan2 = szSymbol[3];
if(cSymbols == 2) { float b = strtof(pScan2, &pScan2);
pMaterial->setReflection(Vector3::Create(r, r, r)); pMaterial->setDiffuse(Vector3::Create(r, g, b));
} else if(cSymbols == 4) { }
pScan2 = szSymbol[2]; } else if(strcmp(szSymbol[0], "ks") == 0) {
float g = strtof(pScan2, &pScan2); char *pScan2 = szSymbol[1];
pScan2 = szSymbol[3]; float r = strtof(pScan2, &pScan2);
float b = strtof(pScan2, &pScan2); if(cSymbols == 2) {
pMaterial->setReflection(Vector3::Create(r, g, b)); pMaterial->setSpecular(Vector3::Create(r, r, r));
} } else if(cSymbols == 4) {
} else if(strcmp(szSymbol[0], "tr") == 0) { pScan2 = szSymbol[2];
char *pScan2 = szSymbol[1]; float g = strtof(pScan2, &pScan2);
float a = strtof(pScan2, &pScan2); pScan2 = szSymbol[3];
pMaterial->setTransparency(a); float b = strtof(pScan2, &pScan2);
} else if(strcmp(szSymbol[0], "ns") == 0) { pMaterial->setSpecular(Vector3::Create(r, g, b));
char *pScan2 = szSymbol[1]; }
float a = strtof(pScan2, &pScan2); } else if(strcmp(szSymbol[0], "kr") == 0) {
pMaterial->setShininess(a); char *pScan2 = szSymbol[1];
} else if(strncmp(szSymbol[0], "map", 3) == 0) { float r = strtof(pScan2, &pScan2);
// Truncate file extension if(cSymbols == 2) {
char *pScan2 = szSymbol[1]; pMaterial->setReflection(Vector3::Create(r, r, r));
char *pLastPeriod = NULL; } else if(cSymbols == 4) {
while(*pScan2 != '\0') { pScan2 = szSymbol[2];
if(*pScan2 == '.') { float g = strtof(pScan2, &pScan2);
pLastPeriod = pScan2; pScan2 = szSymbol[3];
} float b = strtof(pScan2, &pScan2);
pScan2++; pMaterial->setReflection(Vector3::Create(r, g, b));
} }
if(pLastPeriod) { } else if(strcmp(szSymbol[0], "tr") == 0) {
*pLastPeriod = '\0'; char *pScan2 = szSymbol[1];
} float a = strtof(pScan2, &pScan2);
pMaterial->setTransparency(a);
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f); } else if(strcmp(szSymbol[0], "ns") == 0) {
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f); char *pScan2 = szSymbol[1];
float a = strtof(pScan2, &pScan2);
int iScanSymbol = 2; pMaterial->setShininess(a);
int iScaleParam = -1; } else if(strncmp(szSymbol[0], "map", 3) == 0) {
int iOffsetParam = -1; // Truncate file extension
while(iScanSymbol < cSymbols) { char *pScan2 = szSymbol[1];
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) { char *pLastPeriod = NULL;
// Scale while(*pScan2 != '\0') {
iScaleParam = 0; if(*pScan2 == '.') {
iOffsetParam = -1; pLastPeriod = pScan2;
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) { }
// Offset pScan2++;
iOffsetParam = 0; }
iScaleParam = -1; if(pLastPeriod) {
} else { *pLastPeriod = '\0';
char *pScan3 = szSymbol[iScanSymbol]; }
float v = strtof(pScan3, &pScan3);
if(iScaleParam == 0) { Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
texture_scale.x = v; Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
iScaleParam++;
} else if(iScaleParam == 1) { int iScanSymbol = 2;
texture_scale.y = v; int iScaleParam = -1;
iScaleParam++; int iOffsetParam = -1;
} else if(iOffsetParam == 0) { while(iScanSymbol < cSymbols) {
texture_offset.x = v; if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
iOffsetParam++; // Scale
} else if(iOffsetParam == 1) { iScaleParam = 0;
texture_offset.y = v; iOffsetParam = -1;
iOffsetParam++; } else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
} // Offset
} iOffsetParam = 0;
iScanSymbol++; iScaleParam = -1;
} } else {
char *pScan3 = szSymbol[iScanSymbol];
if(strcmp(szSymbol[0], "map_ka") == 0) { float v = strtof(pScan3, &pScan3);
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset); if(iScaleParam == 0) {
} else if(strcmp(szSymbol[0], "map_kd") == 0) { texture_scale.x = v;
pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset); iScaleParam++;
} else if(strcmp(szSymbol[0], "map_ks") == 0) { } else if(iScaleParam == 1) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset); texture_scale.y = v;
} else if(strcmp(szSymbol[0], "map_normal") == 0) { iScaleParam++;
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset); } else if(iOffsetParam == 0) {
} else if(strcmp(szSymbol[0], "map_reflection") == 0) { texture_offset.x = v;
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset); iOffsetParam++;
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) { } else if(iOffsetParam == 1) {
pMaterial->setReflectionCube(szSymbol[1]); texture_offset.y = v;
} iOffsetParam++;
} }
} }
} iScanSymbol++;
} }
} if(strcmp(szSymbol[0], "map_ka") == 0) {
data->unlock(); pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
delete data; } else if(strcmp(szSymbol[0], "map_kd") == 0) {
return true; pMaterial->setDiffuseMap(szSymbol[1], texture_scale, texture_offset);
} } else if(strcmp(szSymbol[0], "map_ks") == 0) {
pMaterial->setSpecularMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_normal") == 0) {
pMaterial->setNormalMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflection") == 0) {
pMaterial->setReflectionMap(szSymbol[1], texture_scale, texture_offset);
} else if(strcmp(szSymbol[0], "map_reflectioncube") == 0) {
pMaterial->setReflectionCube(szSymbol[1]);
}
}
}
}
}
}
data->unlock();
delete data;
return pMaterial;
}

View File

@@ -32,11 +32,10 @@
#ifndef KRMATERIALMANAGER_H #ifndef KRMATERIALMANAGER_H
#define KRMATERIALMANAGER_H #define KRMATERIALMANAGER_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRMaterial.h" #include "KRMaterial.h"
#include "KRTextureManager.h" #include "KRTextureManager.h"
#include "KRMaterialManager.h" #include "KRMaterialManager.h"
@@ -44,12 +43,15 @@
using std::map; using std::map;
class KRMaterialManager : public KRContextObject { class KRMaterialManager : public KRResourceManager {
public: public:
KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager); KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager);
virtual ~KRMaterialManager(); virtual ~KRMaterialManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
bool load(const char *szName, KRDataBlock *data); KRMaterial* load(const char *szName, KRDataBlock *data);
void add(KRMaterial *new_material); void add(KRMaterial *new_material);
KRMaterial *getMaterial(const std::string &name); KRMaterial *getMaterial(const std::string &name);
@@ -61,7 +63,7 @@ public:
private: private:
unordered_map<std::string, KRMaterial *> m_materials; unordered_map<std::string, KRMaterial *> m_materials;
KRTextureManager *m_pTextureManager; KRTextureManager *m_pTextureManager;
KRShaderManager *m_pShaderManager; KRPipelineManager *m_pPipelineManager;
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -60,8 +60,7 @@ class KRNode;
class KRMesh : public KRResource { class KRMesh : public KRResource {
public: public:
static void parseName(const std::string& name, std::string& lodBaseName, int& lodCoverage);
KRMesh(KRContext &context, std::string name, KRDataBlock *data); KRMesh(KRContext &context, std::string name, KRDataBlock *data);
KRMesh(KRContext &context, std::string name); KRMesh(KRContext &context, std::string name);

View File

@@ -1,69 +1,69 @@
// //
// KRMeshCube.cpp // KRMeshCube.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRMeshCube.h" #include "KRMeshCube.h"
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube") KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0)); mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0)); mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0)); mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0)); mi.vertices.push_back(Vector3::Create(-1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0)); mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0)); mi.vertices.push_back(Vector3::Create(-1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0)); mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0)); mi.vertices.push_back(Vector3::Create(1.0, 1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0)); mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0)); mi.vertices.push_back(Vector3::Create(1.0,-1.0, 1.0));
mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0)); mi.vertices.push_back(Vector3::Create(1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0)); mi.vertices.push_back(Vector3::Create(-1.0,-1.0,-1.0));
mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0)); mi.vertices.push_back(Vector3::Create(1.0, 1.0,-1.0));
mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0)); mi.vertices.push_back(Vector3::Create(-1.0, 1.0,-1.0));
mi.submesh_starts.push_back(0); mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size()); mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP; mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshCube::~KRMeshCube() KRMeshCube::~KRMeshCube()
{ {
} }

View File

@@ -38,23 +38,20 @@
#include "KRMeshQuad.h" #include "KRMeshQuad.h"
#include "KRMeshSphere.h" #include "KRMeshSphere.h"
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) { KRMeshManager::KRMeshManager(KRContext &context) : KRResourceManager(context) {
m_currentVBO = NULL; m_currentVBO = NULL;
m_vboMemUsed = 0; m_vboMemUsed = 0;
m_memoryTransferredThisFrame = 0; m_memoryTransferredThisFrame = 0;
m_first_frame = true; m_first_frame = true;
m_streamerComplete = true; m_streamerComplete = true;
addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults addModel(new KRMeshCube(context));
addModel(new KRMeshQuad(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults addModel(new KRMeshQuad(context));
addModel(new KRMeshSphere(context)); addModel(new KRMeshSphere(context));
m_draw_call_logging_enabled = false; m_draw_call_logging_enabled = false;
m_draw_call_log_used = false; m_draw_call_log_used = false;
// ---- Initialize stock models ---- // ---- Initialize stock models ----
static const GLfloat _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = { static const GLfloat _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = {
1.0, 1.0, 1.0, 1.0, 1.0, 1.0,
-1.0, 1.0, 1.0, -1.0, 1.0, 1.0,
@@ -105,6 +102,29 @@ KRMeshManager::~KRMeshManager() {
m_models.empty(); m_models.empty();
} }
KRResource* KRMeshManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("krmesh") == 0) {
return loadModel(name.c_str(), data);
}
return nullptr;
}
KRResource* KRMeshManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("krmesh") == 0) {
std::string lodBaseName;
int lodCoverage;
KRMesh::parseName(name, lodBaseName, lodCoverage);
std::vector<KRMesh*> models = getModel(lodBaseName.c_str());
for (KRMesh* mesh : models) {
if (mesh->getLODCoverage() == lodCoverage) {
return mesh;
}
}
}
return nullptr;
}
KRMesh *KRMeshManager::loadModel(const char *szName, KRDataBlock *pData) { KRMesh *KRMeshManager::loadModel(const char *szName, KRDataBlock *pData) {
KRMesh *pModel = new KRMesh(*m_pContext, szName, pData); KRMesh *pModel = new KRMesh(*m_pContext, szName, pData);
addModel(pModel); addModel(pModel);
@@ -401,32 +421,32 @@ KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) { for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) {
vertex_data[iVertex].vertex.x = -1.0f; vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = -1.0f; vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
vertex_data[iVertex].vertex.x = 1.0f; vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f; vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
vertex_data[iVertex].vertex.x = -1.0f; vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f; vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
vertex_data[iVertex].vertex.x = -1.0f; vertex_data[iVertex].vertex.x = -1.0f;
vertex_data[iVertex].vertex.y = 1.0f; vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
vertex_data[iVertex].vertex.x = 1.0f; vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = -1.0f; vertex_data[iVertex].vertex.y = -1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
vertex_data[iVertex].vertex.x = 1.0f; vertex_data[iVertex].vertex.x = 1.0f;
vertex_data[iVertex].vertex.y = 1.0f; vertex_data[iVertex].vertex.y = 1.0f;
vertex_data[iVertex].vertex.z = iPlane; vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
iVertex++; iVertex++;
} }
@@ -481,7 +501,7 @@ long KRMeshManager::getMemoryTransferedThisFrame()
} }
int KRMeshManager::getActiveVBOCount() size_t KRMeshManager::getActiveVBOCount()
{ {
return m_vbosActive.size(); return m_vbosActive.size();
} }

View File

@@ -33,6 +33,8 @@
#define KRMESHMANAGER_H #define KRMESHMANAGER_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
#include "KRNode.h" #include "KRNode.h"
@@ -40,13 +42,16 @@
class KRContext; class KRContext;
class KRMesh; class KRMesh;
class KRMeshManager : public KRContextObject { class KRMeshManager : public KRResourceManager {
public: public:
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500; static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000; static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
KRMeshManager(KRContext &context); KRMeshManager(KRContext &context);
virtual ~KRMeshManager(); virtual ~KRMeshManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
void startFrame(float deltaTime); void startFrame(float deltaTime);
void endFrame(float deltaTime); void endFrame(float deltaTime);
@@ -88,7 +93,7 @@ public:
KRVBOData(const KRVBOData& o) = delete; KRVBOData(const KRVBOData& o) = delete;
KRVBOData& operator=(const KRVBOData& o) = delete; KRVBOData& operator=(const KRVBOData& o) = delete;
long getSize() { return m_size; } long getSize() { return (long)m_size; }
void resetPoolExpiry(float lodCoverage); void resetPoolExpiry(float lodCoverage);
long getLastFrameUsed() { return m_last_frame_used; } long getLastFrameUsed() { return m_last_frame_used; }
@@ -150,7 +155,7 @@ public:
long getMemoryTransferedThisFrame(); long getMemoryTransferedThisFrame();
int getActiveVBOCount(); size_t getActiveVBOCount();
struct draw_call_info { struct draw_call_info {
KRNode::RenderPass pass; KRNode::RenderPass pass;

View File

@@ -1,63 +1,63 @@
// //
// KRMeshQuad.cpp // KRMeshQuad.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRMeshQuad.h" #include "KRMeshQuad.h"
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad") KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(-1.0f, -1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(1.0f, -1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(-1.0f, 1.0f, 0.0f));
mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f)); mi.vertices.push_back(Vector3::Create(1.0f, 1.0f, 0.0f));
mi.uva.push_back(Vector2::Create(0.0f, 0.0f)); mi.uva.push_back(Vector2::Create(0.0f, 0.0f));
mi.uva.push_back(Vector2::Create(1.0f, 0.0f)); mi.uva.push_back(Vector2::Create(1.0f, 0.0f));
mi.uva.push_back(Vector2::Create(0.0f, 1.0f)); mi.uva.push_back(Vector2::Create(0.0f, 1.0f));
mi.uva.push_back(Vector2::Create(1.0f, 1.0f)); mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
mi.submesh_starts.push_back(0); mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size()); mi.submesh_lengths.push_back((int)mi.vertices.size());
mi.material_names.push_back(""); mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_STRIP; mi.format = KRENGINE_MODEL_FORMAT_STRIP;
LoadData(mi, true, true); LoadData(mi, true, true);
} }
KRMeshQuad::~KRMeshQuad() KRMeshQuad::~KRMeshQuad()
{ {
} }

View File

@@ -1,135 +1,122 @@
// //
// KRMeshSphere.cpp // KRMeshSphere.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRMeshSphere.h" #include "KRMeshSphere.h"
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere") KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
{ {
m_constant = true; m_constant = true;
KRMesh::mesh_info mi; KRMesh::mesh_info mi;
// Create a triangular facet approximation to a sphere // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/ // Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3; int iterations = 3;
int facet_count = pow(4, iterations) * 8; int facet_count = (int)(pow(4, iterations) * 8.0f);
class Facet3 { std::vector<Triangle3> f = std::vector<Triangle3>(facet_count);
public:
Facet3() { int i,it;
float a;
} Vector3 p[6] = {
~Facet3() { Vector3::Create(0,0,1),
Vector3::Create(0,0,-1),
} Vector3::Create(-1,-1,0),
Vector3 p1; Vector3::Create(1,-1,0),
Vector3 p2; Vector3::Create(1,1,0),
Vector3 p3; Vector3::Create(-1,1,0)
}; };
std::vector<Facet3> f = std::vector<Facet3>(facet_count); Vector3 pa,pb,pc;
int nt = 0,ntold;
int i,it;
float a; /* Create the level 0 object */
Vector3 p[6] = { a = 1.0f / sqrtf(2.0f);
Vector3::Create(0,0,1), for (i=0;i<6;i++) {
Vector3::Create(0,0,-1), p[i].x *= a;
Vector3::Create(-1,-1,0), p[i].y *= a;
Vector3::Create(1,-1,0), }
Vector3::Create(1,1,0), f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4];
Vector3::Create(-1,1,0) f[1][0] = p[0]; f[1][1] = p[4]; f[1][2] = p[5];
}; f[2][0] = p[0]; f[2][1] = p[5]; f[2][2] = p[2];
f[3][0] = p[0]; f[3][1] = p[2]; f[3][2] = p[3];
Vector3 pa,pb,pc; f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3];
int nt = 0,ntold; f[5][0] = p[1]; f[5][1] = p[5]; f[5][2] = p[4];
f[6][0] = p[1]; f[6][1] = p[2]; f[6][2] = p[5];
/* Create the level 0 object */ f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2];
a = 1 / sqrt(2.0); nt = 8;
for (i=0;i<6;i++) {
p[i].x *= a; /* Bisect each edge and move to the surface of a unit sphere */
p[i].y *= a; for (it=0;it<iterations;it++) {
} ntold = nt;
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4]; for (i=0;i<ntold;i++) {
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5]; pa.x = (f[i][0].x + f[i][1].x) / 2;
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2]; pa.y = (f[i][0].y + f[i][1].y) / 2;
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3]; pa.z = (f[i][0].z + f[i][1].z) / 2;
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3]; pb.x = (f[i][1].x + f[i][2].x) / 2;
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4]; pb.y = (f[i][1].y + f[i][2].y) / 2;
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5]; pb.z = (f[i][1].z + f[i][2].z) / 2;
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2]; pc.x = (f[i][2].x + f[i][0].x) / 2;
nt = 8; pc.y = (f[i][2].y + f[i][0].y) / 2;
pc.z = (f[i][2].z + f[i][0].z) / 2;
/* Bisect each edge and move to the surface of a unit sphere */ pa.normalize();
for (it=0;it<iterations;it++) { pb.normalize();
ntold = nt; pc.normalize();
for (i=0;i<ntold;i++) { f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++;
pa.x = (f[i].p1.x + f[i].p2.x) / 2; f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++;
pa.y = (f[i].p1.y + f[i].p2.y) / 2; f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++;
pa.z = (f[i].p1.z + f[i].p2.z) / 2; f[i][0] = pa;
pb.x = (f[i].p2.x + f[i].p3.x) / 2; f[i][1] = pb;
pb.y = (f[i].p2.y + f[i].p3.y) / 2; f[i][2] = pc;
pb.z = (f[i].p2.z + f[i].p3.z) / 2; }
pc.x = (f[i].p3.x + f[i].p1.x) / 2; }
pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2; for(int facet_index=0; facet_index < facet_count; facet_index++) {
pa.normalize(); mi.vertices.push_back(f[facet_index][0]);
pb.normalize(); mi.vertices.push_back(f[facet_index][1]);
pc.normalize(); mi.vertices.push_back(f[facet_index][2]);
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++; }
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++; mi.submesh_starts.push_back(0);
f[i].p1 = pa; mi.submesh_lengths.push_back((int)mi.vertices.size());
f[i].p2 = pb; mi.material_names.push_back("");
f[i].p3 = pc;
}
} mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
LoadData(mi, true, true);
for(int facet_index=0; facet_index < facet_count; facet_index++) { }
mi.vertices.push_back(f[facet_index].p1);
mi.vertices.push_back(f[facet_index].p2); KRMeshSphere::~KRMeshSphere()
mi.vertices.push_back(f[facet_index].p3); {
}
}
mi.submesh_starts.push_back(0);
mi.submesh_lengths.push_back(mi.vertices.size());
mi.material_names.push_back("");
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
LoadData(mi, true, true);
}
KRMeshSphere::~KRMeshSphere()
{
}

View File

@@ -1,263 +1,263 @@
// //
// KRModel.cpp // KRModel.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRModel.h" #include "KRModel.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRMesh.h" #include "KRMesh.h"
KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) { KRModel::KRModel(KRScene &scene, std::string instance_name, std::string model_name, std::string light_map, float lod_min_coverage, bool receives_shadow, bool faces_camera, Vector3 rim_color, float rim_power) : KRNode(scene, instance_name) {
m_lightMap = light_map; m_lightMap = light_map;
m_pLightMap = NULL; m_pLightMap = NULL;
m_model_name = model_name; m_model_name = model_name;
m_min_lod_coverage = lod_min_coverage; m_min_lod_coverage = lod_min_coverage;
m_receivesShadow = receives_shadow; m_receivesShadow = receives_shadow;
m_faces_camera = faces_camera; m_faces_camera = faces_camera;
m_rim_color = rim_color; m_rim_color = rim_color;
m_rim_power = rim_power; m_rim_power = rim_power;
m_boundsCachedMat.c[0] = -1.0f; m_boundsCachedMat.c[0] = -1.0f;
m_boundsCachedMat.c[1] = -1.0f; m_boundsCachedMat.c[1] = -1.0f;
m_boundsCachedMat.c[2] = -1.0f; m_boundsCachedMat.c[2] = -1.0f;
m_boundsCachedMat.c[3] = -1.0f; m_boundsCachedMat.c[3] = -1.0f;
m_boundsCachedMat.c[4] = -1.0f; m_boundsCachedMat.c[4] = -1.0f;
m_boundsCachedMat.c[5] = -1.0f; m_boundsCachedMat.c[5] = -1.0f;
m_boundsCachedMat.c[6] = -1.0f; m_boundsCachedMat.c[6] = -1.0f;
m_boundsCachedMat.c[7] = -1.0f; m_boundsCachedMat.c[7] = -1.0f;
m_boundsCachedMat.c[8] = -1.0f; m_boundsCachedMat.c[8] = -1.0f;
m_boundsCachedMat.c[9] = -1.0f; m_boundsCachedMat.c[9] = -1.0f;
m_boundsCachedMat.c[10] = -1.0f; m_boundsCachedMat.c[10] = -1.0f;
m_boundsCachedMat.c[11] = -1.0f; m_boundsCachedMat.c[11] = -1.0f;
m_boundsCachedMat.c[12] = -1.0f; m_boundsCachedMat.c[12] = -1.0f;
m_boundsCachedMat.c[13] = -1.0f; m_boundsCachedMat.c[13] = -1.0f;
m_boundsCachedMat.c[14] = -1.0f; m_boundsCachedMat.c[14] = -1.0f;
m_boundsCachedMat.c[15] = -1.0f; m_boundsCachedMat.c[15] = -1.0f;
} }
KRModel::~KRModel() { KRModel::~KRModel() {
} }
std::string KRModel::getElementName() { std::string KRModel::getElementName() {
return "model"; return "model";
} }
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("mesh", m_model_name.c_str()); e->SetAttribute("mesh", m_model_name.c_str());
e->SetAttribute("light_map", m_lightMap.c_str()); e->SetAttribute("light_map", m_lightMap.c_str());
e->SetAttribute("lod_min_coverage", m_min_lod_coverage); e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false"); e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false"); e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero()); kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
e->SetAttribute("rim_power", m_rim_power); e->SetAttribute("rim_power", m_rim_power);
return e; return e;
} }
void KRModel::setRimColor(const Vector3 &rim_color) void KRModel::setRimColor(const Vector3 &rim_color)
{ {
m_rim_color = rim_color; m_rim_color = rim_color;
} }
void KRModel::setRimPower(float rim_power) void KRModel::setRimPower(float rim_power)
{ {
m_rim_power = rim_power; m_rim_power = rim_power;
} }
Vector3 KRModel::getRimColor() Vector3 KRModel::getRimColor()
{ {
return m_rim_color; return m_rim_color;
} }
float KRModel::getRimPower() float KRModel::getRimPower()
{ {
return m_rim_power; return m_rim_power;
} }
void KRModel::setLightMap(const std::string &name) void KRModel::setLightMap(const std::string &name)
{ {
m_lightMap = name; m_lightMap = name;
m_pLightMap = NULL; m_pLightMap = NULL;
} }
std::string KRModel::getLightMap() std::string KRModel::getLightMap()
{ {
return m_lightMap; return m_lightMap;
} }
void KRModel::loadModel() { void KRModel::loadModel() {
if(m_models.size() == 0) { if(m_models.size() == 0) {
std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first std::vector<KRMesh *> models = m_pContext->getMeshManager()->getModel(m_model_name.c_str()); // The model manager returns the LOD levels in sorted order, with the highest detail first
unordered_map<KRMesh *, std::vector<KRBone *> > bones; unordered_map<KRMesh *, std::vector<KRBone *> > bones;
if(models.size() > 0) { if(models.size() > 0) {
bool all_bones_found = true; bool all_bones_found = true;
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) { for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
KRMesh *model = *model_itr; KRMesh *model = *model_itr;
std::vector<KRBone *> model_bones; std::vector<KRBone *> model_bones;
int bone_count = model->getBoneCount(); int bone_count = model->getBoneCount();
for(int bone_index=0; bone_index < bone_count; bone_index++) { for(int bone_index=0; bone_index < bone_count; bone_index++) {
KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index))); KRBone *matching_bone = dynamic_cast<KRBone *>(getScene().getRootNode()->find<KRNode>(model->getBoneName(bone_index)));
if(matching_bone) { if(matching_bone) {
model_bones.push_back(matching_bone); model_bones.push_back(matching_bone);
} else { } else {
all_bones_found = false; // Reject when there are any missing bones or multiple matches all_bones_found = false; // Reject when there are any missing bones or multiple matches
} }
} }
bones[model] = model_bones; bones[model] = model_bones;
} }
if(all_bones_found) { if(all_bones_found) {
m_models = models; m_models = models;
m_bones = bones; m_bones = bones;
getScene().notify_sceneGraphModify(this); getScene().notify_sceneGraphModify(this);
} }
invalidateBounds(); invalidateBounds();
} }
} }
} }
void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRModel::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) { if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
preStream(viewport); preStream(viewport);
} }
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) { if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_ADDITIVE_PARTICLES && renderPass != KRNode::RENDER_PASS_PARTICLE_OCCLUSION && renderPass != KRNode::RENDER_PASS_VOLUMETRIC_EFFECTS_ADDITIVE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS && renderPass != KRNode::RENDER_PASS_PRESTREAM) {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied // Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
/* /*
float lod_coverage = 0.0f; float lod_coverage = 0.0f;
if(m_models.size() > 1) { if(m_models.size() > 1) {
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
} else if(viewport.visible(getBounds())) { } else if(viewport.visible(getBounds())) {
lod_coverage = 1.0f; lod_coverage = 1.0f;
} }
*/ */
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
if(lod_coverage > m_min_lod_coverage) { if(lod_coverage > m_min_lod_coverage) {
// ---===--- Select the best LOD model based on screen coverage ---===--- // ---===--- Select the best LOD model based on screen coverage ---===---
std::vector<KRMesh *>::iterator itr=m_models.begin(); std::vector<KRMesh *>::iterator itr=m_models.begin();
KRMesh *pModel = *itr++; KRMesh *pModel = *itr++;
while(itr != m_models.end()) { while(itr != m_models.end()) {
KRMesh *pLODModel = *itr++; KRMesh *pLODModel = *itr++;
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) { if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
pModel = pLODModel; pModel = pLODModel;
} else { } else {
break; break;
} }
} }
if(m_pLightMap == NULL && m_lightMap.size()) { if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
} }
if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) { if(m_pLightMap && pCamera->settings.bEnableLightMap && renderPass != RENDER_PASS_SHADOWMAP && renderPass != RENDER_PASS_GENERATE_SHADOWMAPS) {
m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); m_pContext->getTextureManager()->selectTexture(5, m_pLightMap, lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
} }
Matrix4 matModel = getModelMatrix(); Matrix4 matModel = getModelMatrix();
if(m_faces_camera) { if(m_faces_camera) {
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero()); Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
Vector3 camera_pos = viewport.getCameraPosition(); Vector3 camera_pos = viewport.getCameraPosition();
matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel; matModel = Quaternion::Create(Vector3::Forward(), Vector3::Normalize(camera_pos - model_center)).rotationMatrix() * matModel;
} }
pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage); pModel->render(getName(), pCamera, point_lights, directional_lights, spot_lights, viewport, matModel, m_pLightMap, renderPass, m_bones[pModel], m_rim_color, m_rim_power, lod_coverage);
} }
} }
} }
} }
void KRModel::preStream(const KRViewport &viewport) void KRModel::preStream(const KRViewport &viewport)
{ {
loadModel(); loadModel();
float lod_coverage = viewport.coverage(getBounds()); float lod_coverage = viewport.coverage(getBounds());
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
(*itr)->preStream(lod_coverage); (*itr)->preStream(lod_coverage);
} }
if(m_pLightMap == NULL && m_lightMap.size()) { if(m_pLightMap == NULL && m_lightMap.size()) {
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap); m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
} }
if(m_pLightMap) { if(m_pLightMap) {
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP); m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
} }
} }
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport) kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
{ {
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport); kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
loadModel(); loadModel();
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) { for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel()); stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
} }
return stream_level; return stream_level;
} }
AABB KRModel::getBounds() { AABB KRModel::getBounds() {
loadModel(); loadModel();
if(m_models.size() > 0) { if(m_models.size() > 0) {
if(m_faces_camera) { if(m_faces_camera) {
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
float max_dimension = normal_bounds.longest_radius(); float max_dimension = normal_bounds.longest_radius();
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension)); return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
} else { } else {
if(!(m_boundsCachedMat == getModelMatrix())) { if(!(m_boundsCachedMat == getModelMatrix())) {
m_boundsCachedMat = getModelMatrix(); m_boundsCachedMat = getModelMatrix();
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix()); m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
} }
return m_boundsCached; return m_boundsCached;
} }
} else { } else {
return AABB::Infinite(); return AABB::Infinite();
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,7 @@ class Matrix4;
class AABB; class AABB;
} // namespace kraken } // namespace kraken
class KRCamera; class KRCamera;
class KRShaderManager; class KRPipelineManager;
class KRMeshManager; class KRMeshManager;
class KRMaterialManager; class KRMaterialManager;
class KRTextureManager; class KRTextureManager;

View File

@@ -1,156 +1,156 @@
// //
// KROctree.cpp // KROctree.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "public/kraken.h" #include "public/kraken.h"
#include "KROctree.h" #include "KROctree.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
KROctree::KROctree() KROctree::KROctree()
{ {
m_pRootNode = NULL; m_pRootNode = NULL;
} }
KROctree::~KROctree() KROctree::~KROctree()
{ {
if(m_pRootNode) { if(m_pRootNode) {
delete m_pRootNode; delete m_pRootNode;
} }
} }
void KROctree::add(KRNode *pNode) void KROctree::add(KRNode *pNode)
{ {
AABB nodeBounds = pNode->getBounds(); AABB nodeBounds = pNode->getBounds();
if(nodeBounds == AABB::Zero()) { if(nodeBounds == AABB::Zero()) {
// This item is not visible, don't add it to the octree or outer scene nodes // This item is not visible, don't add it to the octree or outer scene nodes
} else if(nodeBounds == AABB::Infinite()) { } else if(nodeBounds == AABB::Infinite()) {
// This item is infinitely large; we track it separately // This item is infinitely large; we track it separately
m_outerSceneNodes.insert(pNode); m_outerSceneNodes.insert(pNode);
} else { } else {
if(m_pRootNode == NULL) { if(m_pRootNode == NULL) {
// First item inserted, create a node large enough to fit it // First item inserted, create a node large enough to fit it
m_pRootNode = new KROctreeNode(NULL, nodeBounds); m_pRootNode = new KROctreeNode(NULL, nodeBounds);
m_pRootNode->add(pNode); m_pRootNode->add(pNode);
} else { } else {
// Keep encapsulating the root node until the new root contains the inserted node // Keep encapsulating the root node until the new root contains the inserted node
bool bInsideRoot = false; bool bInsideRoot = false;
while(!bInsideRoot) { while(!bInsideRoot) {
AABB rootBounds = m_pRootNode->getBounds(); AABB rootBounds = m_pRootNode->getBounds();
Vector3 rootSize = rootBounds.size(); Vector3 rootSize = rootBounds.size();
if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) { if(nodeBounds.min.x < rootBounds.min.x || nodeBounds.min.y < rootBounds.min.y || nodeBounds.min.z < rootBounds.min.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode); m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min - rootSize, rootBounds.max), 7, m_pRootNode);
} else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) { } else if(nodeBounds.max.x > rootBounds.max.x || nodeBounds.max.y > rootBounds.max.y || nodeBounds.max.z > rootBounds.max.z) {
m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode); m_pRootNode = new KROctreeNode(NULL, AABB::Create(rootBounds.min, rootBounds.max + rootSize), 0, m_pRootNode);
} else { } else {
bInsideRoot = true; bInsideRoot = true;
} }
} }
m_pRootNode->add(pNode); m_pRootNode->add(pNode);
} }
} }
} }
void KROctree::remove(KRNode *pNode) void KROctree::remove(KRNode *pNode)
{ {
if(!m_outerSceneNodes.erase(pNode)) { if(!m_outerSceneNodes.erase(pNode)) {
if(m_pRootNode) { if(m_pRootNode) {
pNode->removeFromOctreeNodes(); pNode->removeFromOctreeNodes();
} }
} }
shrink(); shrink();
} }
void KROctree::update(KRNode *pNode) void KROctree::update(KRNode *pNode)
{ {
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node // TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
remove(pNode); remove(pNode);
add(pNode); add(pNode);
shrink(); shrink();
} }
void KROctree::shrink() void KROctree::shrink()
{ {
if(m_pRootNode) { if(m_pRootNode) {
while(m_pRootNode->canShrinkRoot()) { while(m_pRootNode->canShrinkRoot()) {
KROctreeNode *newRoot = m_pRootNode->stripChild(); KROctreeNode *newRoot = m_pRootNode->stripChild();
delete m_pRootNode; delete m_pRootNode;
m_pRootNode = newRoot; m_pRootNode = newRoot;
if(m_pRootNode == NULL) return; if(m_pRootNode == NULL) return;
} }
} }
} }
KROctreeNode *KROctree::getRootNode() KROctreeNode *KROctree::getRootNode()
{ {
return m_pRootNode; return m_pRootNode;
} }
std::set<KRNode *> &KROctree::getOuterSceneNodes() std::set<KRNode *> &KROctree::getOuterSceneNodes()
{ {
return m_outerSceneNodes; return m_outerSceneNodes;
} }
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
std::vector<KRCollider *> outer_colliders; std::vector<KRCollider *> outer_colliders;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
if(collider) { if(collider) {
outer_colliders.push_back(collider); outer_colliders.push_back(collider);
} }
} }
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) { for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; if((*itr)->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
} }
if(m_pRootNode) { if(m_pRootNode) {
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
} }
return hit_found; return hit_found;
} }
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
if(collider) { if(collider) {
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
} }
} }
if(m_pRootNode) { if(m_pRootNode) {
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
} }
return hit_found; return hit_found;
} }
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask) bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
std::vector<KRCollider *> outer_colliders; std::vector<KRCollider *> outer_colliders;
for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) { for(std::set<KRNode *>::iterator outer_nodes_itr=m_outerSceneNodes.begin(); outer_nodes_itr != m_outerSceneNodes.end(); outer_nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
if(collider) { if(collider) {
outer_colliders.push_back(collider); outer_colliders.push_back(collider);
} }
} }
for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) { for(std::vector<KRCollider *>::iterator itr=outer_colliders.begin(); itr != outer_colliders.end(); itr++) {
if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if((*itr)->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
if(m_pRootNode) { if(m_pRootNode) {
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
return hit_found; return hit_found;
} }

View File

@@ -1,290 +1,290 @@
// //
// KROctreeNode.cpp // KROctreeNode.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-08-29. // Created by Kearwood Gilbert on 2012-08-29.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KROctreeNode.h" #include "KROctreeNode.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCollider.h" #include "KRCollider.h"
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
{ {
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for(int i=0; i<8; i++) m_children[i] = NULL;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = false; m_activeQuery = false;
} }
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds) KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds, int iChild, KROctreeNode *pChild) : m_bounds(bounds)
{ {
// This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it // This constructor is used when expanding the octree and replacing the root node with a new root that encapsulates it
m_parent = parent; m_parent = parent;
for(int i=0; i<8; i++) m_children[i] = NULL; for(int i=0; i<8; i++) m_children[i] = NULL;
m_children[iChild] = pChild; m_children[iChild] = pChild;
pChild->m_parent = this; pChild->m_parent = this;
m_occlusionQuery = 0; m_occlusionQuery = 0;
m_occlusionTested = false; m_occlusionTested = false;
m_activeQuery = false; m_activeQuery = false;
} }
KROctreeNode::~KROctreeNode() KROctreeNode::~KROctreeNode()
{ {
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i] != NULL) { if(m_children[i] != NULL) {
delete m_children[i]; delete m_children[i];
} }
} }
if(m_occlusionTested) { if(m_occlusionTested) {
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
} }
} }
void KROctreeNode::beginOcclusionQuery() void KROctreeNode::beginOcclusionQuery()
{ {
if(!m_occlusionTested){ if(!m_occlusionTested){
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery)); GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery)); GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
#else #else
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery)); GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
#endif #endif
m_occlusionTested = true; m_occlusionTested = true;
m_activeQuery = true; m_activeQuery = true;
} }
} }
void KROctreeNode::endOcclusionQuery() void KROctreeNode::endOcclusionQuery()
{ {
if(m_activeQuery) { if(m_activeQuery) {
// Only end a query if we started one // Only end a query if we started one
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE || defined(ANDROID)
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT)); GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
#else #else
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED)); GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
#endif #endif
} }
} }
AABB KROctreeNode::getBounds() AABB KROctreeNode::getBounds()
{ {
return m_bounds; return m_bounds;
} }
void KROctreeNode::add(KRNode *pNode) void KROctreeNode::add(KRNode *pNode)
{ {
int iChild = getChildIndex(pNode); int iChild = getChildIndex(pNode);
if(iChild == -1) { if(iChild == -1) {
m_sceneNodes.insert(pNode); m_sceneNodes.insert(pNode);
pNode->addToOctreeNode(this); pNode->addToOctreeNode(this);
} else { } else {
if(m_children[iChild] == NULL) { if(m_children[iChild] == NULL) {
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild)); m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
} }
m_children[iChild]->add(pNode); m_children[iChild]->add(pNode);
} }
} }
AABB KROctreeNode::getChildBounds(int iChild) AABB KROctreeNode::getChildBounds(int iChild)
{ {
Vector3 center = m_bounds.center(); Vector3 center = m_bounds.center();
return AABB::Create( return AABB::Create(
Vector3::Create( Vector3::Create(
(iChild & 1) == 0 ? m_bounds.min.x : center.x, (iChild & 1) == 0 ? m_bounds.min.x : center.x,
(iChild & 2) == 0 ? m_bounds.min.y : center.y, (iChild & 2) == 0 ? m_bounds.min.y : center.y,
(iChild & 4) == 0 ? m_bounds.min.z : center.z), (iChild & 4) == 0 ? m_bounds.min.z : center.z),
Vector3::Create( Vector3::Create(
(iChild & 1) == 0 ? center.x : m_bounds.max.x, (iChild & 1) == 0 ? center.x : m_bounds.max.x,
(iChild & 2) == 0 ? center.y : m_bounds.max.y, (iChild & 2) == 0 ? center.y : m_bounds.max.y,
(iChild & 4) == 0 ? center.z : m_bounds.max.z) (iChild & 4) == 0 ? center.z : m_bounds.max.z)
); );
} }
int KROctreeNode::getChildIndex(KRNode *pNode) int KROctreeNode::getChildIndex(KRNode *pNode)
{ {
for(int iChild=0; iChild < 8; iChild++) { for(int iChild=0; iChild < 8; iChild++) {
if(getChildBounds(iChild).contains(pNode->getBounds())) { if(getChildBounds(iChild).contains(pNode->getBounds())) {
return iChild; return iChild;
} }
} }
return -1; return -1;
} }
void KROctreeNode::trim() void KROctreeNode::trim()
{ {
for(int iChild = 0; iChild < 8; iChild++) { for(int iChild = 0; iChild < 8; iChild++) {
if(m_children[iChild]) { if(m_children[iChild]) {
if(m_children[iChild]->isEmpty()) { if(m_children[iChild]->isEmpty()) {
delete m_children[iChild]; delete m_children[iChild];
m_children[iChild] = NULL; m_children[iChild] = NULL;
} }
} }
} }
} }
void KROctreeNode::remove(KRNode *pNode) void KROctreeNode::remove(KRNode *pNode)
{ {
m_sceneNodes.erase(pNode); m_sceneNodes.erase(pNode);
} }
void KROctreeNode::update(KRNode *pNode) void KROctreeNode::update(KRNode *pNode)
{ {
} }
bool KROctreeNode::isEmpty() const bool KROctreeNode::isEmpty() const
{ {
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
return false; return false;
} }
} }
return m_sceneNodes.empty(); return m_sceneNodes.empty();
} }
bool KROctreeNode::canShrinkRoot() const bool KROctreeNode::canShrinkRoot() const
{ {
int cChildren = 0; int cChildren = 0;
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
cChildren++; cChildren++;
} }
} }
return cChildren <= 1 && m_sceneNodes.empty(); return cChildren <= 1 && m_sceneNodes.empty();
} }
KROctreeNode *KROctreeNode::stripChild() KROctreeNode *KROctreeNode::stripChild()
{ {
// Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree // Return the first found child and update its reference to NULL so that the destructor will not free it. This is used for shrinking the octree
// NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL // NOTE: The caller of this function will be responsible for freeing the child object. It is also possible to return a NULL
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
KROctreeNode *child = m_children[i]; KROctreeNode *child = m_children[i];
child->m_parent = NULL; child->m_parent = NULL;
m_children[i] = NULL; m_children[i] = NULL;
return child; return child;
} }
} }
return NULL; return NULL;
} }
KROctreeNode *KROctreeNode::getParent() KROctreeNode *KROctreeNode::getParent()
{ {
return m_parent; return m_parent;
} }
KROctreeNode **KROctreeNode::getChildren() KROctreeNode **KROctreeNode::getChildren()
{ {
return m_children; return m_children;
} }
std::set<KRNode *> &KROctreeNode::getSceneNodes() std::set<KRNode *> &KROctreeNode::getSceneNodes()
{ {
return m_sceneNodes; return m_sceneNodes;
} }
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask) bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) { if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
// Optimization: If we already have a hit, only search for hits that are closer // Optimization: If we already have a hit, only search for hits that are closer
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
} else { } else {
if(getBounds().intersectsLine(v0, v1)) { if(getBounds().intersectsLine(v0, v1)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) { for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
if(collider) { if(collider) {
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true; if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
} }
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) { if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
hit_found = true; hit_found = true;
} }
} }
} }
} }
} }
return hit_found; return hit_found;
} }
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask) bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
if(hitinfo.didHit()) { if(hitinfo.didHit()) {
// Optimization: If we already have a hit, only search for hits that are closer // Optimization: If we already have a hit, only search for hits that are closer
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask); // Note: This is purposefully lineCast as opposed to RayCast
} else { } else {
if(getBounds().intersectsRay(v0, dir)) { if(getBounds().intersectsRay(v0, dir)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) { for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
if(collider) { if(collider) {
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true; if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
} }
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) { if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
hit_found = true; hit_found = true;
} }
} }
} }
} }
} }
return hit_found; return hit_found;
} }
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask) bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
{ {
bool hit_found = false; bool hit_found = false;
/* /*
// FINDME, TODO - Adapt this optimization to work with sphereCasts // FINDME, TODO - Adapt this optimization to work with sphereCasts
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) { if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
// Optimization: If we already have a hit, only search for hits that are closer // Optimization: If we already have a hit, only search for hits that are closer
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask); hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
} else { } else {
*/ */
AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius)); AABB swept_bounds = AABB::Create(Vector3::Create(KRMIN(v0.x, v1.x) - radius, KRMIN(v0.y, v1.y) - radius, KRMIN(v0.z, v1.z) - radius), Vector3::Create(KRMAX(v0.x, v1.x) + radius, KRMAX(v0.y, v1.y) + radius, KRMAX(v0.z, v1.z) + radius));
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {" // FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
if(getBounds().intersects(swept_bounds)) { if(getBounds().intersects(swept_bounds)) {
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) { for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr); KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
if(collider) { if(collider) {
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true; if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
} }
} }
for(int i=0; i<8; i++) { for(int i=0; i<8; i++) {
if(m_children[i]) { if(m_children[i]) {
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) { if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
hit_found = true; hit_found = true;
} }
} }
} }
} }
// } // }
return hit_found; return hit_found;
} }

View File

@@ -1,89 +1,89 @@
// //
// KRParticleSystemNewtonian.cpp // KRParticleSystemNewtonian.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-11-02. // Created by Kearwood Gilbert on 2012-11-02.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRParticleSystemNewtonian.h" #include "KRParticleSystemNewtonian.h"
#include "KRTexture.h" #include "KRTexture.h"
#include "KRContext.h" #include "KRContext.h"
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name) KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
{ {
m_particlesAbsoluteTime = 0.0f; m_particlesAbsoluteTime = 0.0f;
} }
KRParticleSystemNewtonian::~KRParticleSystemNewtonian() KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
{ {
} }
std::string KRParticleSystemNewtonian::getElementName() std::string KRParticleSystemNewtonian::getElementName()
{ {
return "newtonian_particles"; return "newtonian_particles";
} }
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e) void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
{ {
KRParticleSystem::loadXML(e); KRParticleSystem::loadXML(e);
} }
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent); tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
return e; return e;
} }
AABB KRParticleSystemNewtonian::getBounds() AABB KRParticleSystemNewtonian::getBounds()
{ {
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime) void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
{ {
KRParticleSystem::physicsUpdate(deltaTime); KRParticleSystem::physicsUpdate(deltaTime);
m_particlesAbsoluteTime += deltaTime; m_particlesAbsoluteTime += deltaTime;
} }
bool KRParticleSystemNewtonian::hasPhysics() bool KRParticleSystemNewtonian::hasPhysics()
{ {
return true; return true;
} }
void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRParticleSystemNewtonian::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(viewport.visible(getBounds())) { if(viewport.visible(getBounds())) {
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare"); KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE); m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
int particle_count = 10000; int particle_count = 10000;
KRShader *pParticleShader = m_pContext->getShaderManager()->getShader("dust_particle", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pParticleShader = m_pContext->getPipelineManager()->getPipeline("dust_particle", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
Vector3 rim_color; Vector4 fade_color; // Vector3 rim_color; Vector4 fade_color;
if(getContext().getShaderManager()->selectShader(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f); pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
KRDataBlock index_data; KRDataBlock index_data;
m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f); m_pContext->getMeshManager()->bindVBO(m_pContext->getMeshManager()->getRandomParticles(), index_data, (1 << KRMesh::KRENGINE_ATTRIB_VERTEX) | (1 << KRMesh::KRENGINE_ATTRIB_TEXUVA), false, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
} }
} }
} }
} }

581
kraken/KRPipeline.cpp Normal file
View File

@@ -0,0 +1,581 @@
//
// KRPipeline.cpp
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRPipeline.h"
#include "assert.h"
#include "KRLight.h"
#include "KRDirectionalLight.h"
#include "KRSpotLight.h"
#include "KRPointLight.h"
const char *KRPipeline::KRENGINE_UNIFORM_NAMES[] = {
"material_ambient", // KRENGINE_UNIFORM_MATERIAL_AMBIENT
"material_diffuse", // KRENGINE_UNIFORM_MATERIAL_DIFFUSE
"material_specular", // KRENGINE_UNIFORM_MATERIAL_SPECULAR
"material_reflection", // KRENGINE_UNIFORM_MATERIAL_REFLECTION
"material_alpha", // KRENGINE_UNIFORM_MATERIAL_ALPHA
"material_shininess", // KRENGINE_UNIFORM_MATERIAL_SHININESS
"light_position", // KRENGINE_UNIFORM_LIGHT_POSITION
"light_direction_model_space", // KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE
"light_direction_view_space", // KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE
"light_color", // KRENGINE_UNIFORM_LIGHT_COLOR
"light_decay_start", // KRENGINE_UNIFORM_LIGHT_DECAY_START
"light_cutoff", // KRENGINE_UNIFORM_LIGHT_CUTOFF
"light_intensity", // KRENGINE_UNIFORM_LIGHT_INTENSITY
"flare_size", // KRENGINE_UNIFORM_FLARE_SIZE
"view_space_model_origin", // KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN
"mvp_matrix", // KRENGINE_UNIFORM_MVP
"inv_projection_matrix", // KRENGINE_UNIFORM_INVP
"inv_mvp_matrix", // KRENGINE_UNIFORM_INVMVP
"inv_mvp_matrix_no_translate", // KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE
"model_view_inverse_transpose_matrix", // KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE
"model_inverse_transpose_matrix", // KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE
"model_view_matrix", // KRENGINE_UNIFORM_MODEL_VIEW
"model_matrix", // KRENGINE_UNIFORM_MODEL_MATRIX
"projection_matrix", // KRENGINE_UNIFORM_PROJECTION_MATRIX
"camera_position_model_space", // KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE
"viewport", // KRENGINE_UNIFORM_VIEWPORT
"viewport_downsample", // KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE
"diffuseTexture", // KRENGINE_UNIFORM_DIFFUSETEXTURE
"specularTexture", // KRENGINE_UNIFORM_SPECULARTEXTURE
"reflectionCubeTexture", // KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE
"reflectionTexture", // KRENGINE_UNIFORM_REFLECTIONTEXTURE
"normalTexture", // KRENGINE_UNIFORM_NORMALTEXTURE
"diffuseTexture_Scale", // KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE
"specularTexture_Scale", // KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE
"reflectionTexture_Scale", // KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE
"normalTexture_Scale", // KRENGINE_UNIFORM_NORMALTEXTURE_SCALE
"normalTexture_Scale", // KRENGINE_UNIFORM_AMBIENTTEXTURE_SCALE
"diffuseTexture_Offset", // KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET
"specularTexture_Offset", // KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET
"reflectionTexture_Offset", // KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET
"normalTexture_Offset", // KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET
"ambientTexture_Offset", // KRENGINE_UNIFORM_AMBIENTTEXTURE_OFFSET
"shadow_mvp1", // KRENGINE_UNIFORM_SHADOWMVP1
"shadow_mvp2", // KRENGINE_UNIFORM_SHADOWMVP2
"shadow_mvp3", // KRENGINE_UNIFORM_SHADOWMVP3
"shadowTexture1", // KRENGINE_UNIFORM_SHADOWTEXTURE1
"shadowTexture2", // KRENGINE_UNIFORM_SHADOWTEXTURE2
"shadowTexture3", // KRENGINE_UNIFORM_SHADOWTEXTURE3
"lightmapTexture", // KRENGINE_UNIFORM_LIGHTMAPTEXTURE
"gbuffer_frame", // KRENGINE_UNIFORM_GBUFFER_FRAME
"gbuffer_depth", // KRENGINE_UNIFORM_GBUFFER_DEPTH
"depthFrame", // KRENGINE_UNIFORM_DEPTH_FRAME
"volumetricEnvironmentFrame", // KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME
"renderFrame", // KRENGINE_UNIFORM_RENDER_FRAME
"time_absolute", // KRENGINE_UNIFORM_ABSOLUTE_TIME
"fog_near", // KRENGINE_UNIFORM_FOG_NEAR
"fog_far", // KRENGINE_UNIFORM_FOG_FAR
"fog_density", // KRENGINE_UNIFORM_FOG_DENSITY
"fog_color", // KRENGINE_UNIFORM_FOG_COLOR
"fog_scale", // KRENGINE_UNIFORM_FOG_SCALE
"fog_density_premultiplied_exponential", // KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL
"fog_density_premultiplied_squared", // KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED
"slice_depth_scale", // KRENGINE_UNIFORM_SLICE_DEPTH_SCALE
"particle_origin", // KRENGINE_UNIFORM_PARTICLE_ORIGIN
"bone_transforms", // KRENGINE_UNIFORM_BONE_TRANSFORMS
"rim_color", // KRENGINE_UNIFORM_RIM_COLOR
"rim_power", // KRENGINE_UNIFORM_RIM_POWER
"fade_color", // KRENGINE_UNIFORM_FADE_COLOR
};
KRPipeline::KRPipeline(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) : KRContextObject(context)
{
strcpy(m_szKey, szKey);
m_iProgram = 0;
GLuint vertexShader = 0, fragShader = 0;
const GLchar *vertSource[2] = {options.c_str(), vertShaderSource.c_str()};
const GLchar *fragSource[2] = {options.c_str(), fragShaderSource.c_str()};
// Create shader program.
GLDEBUG(m_iProgram = glCreateProgram());
// Create and compile vertex shader.
GLDEBUG(vertexShader = glCreateShader(GL_VERTEX_SHADER));
GLDEBUG(glShaderSource(vertexShader, 2, vertSource, NULL));
GLDEBUG(glCompileShader(vertexShader));
// Report any compile issues to stderr
GLint logLength = 0;
GLDEBUG(glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetShaderInfoLog fails
GLDEBUG(glGetShaderInfoLog(vertexShader, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to compile vertex shader: %s\nShader compile log:\n%s", szKey, log);
free(log);
}
// Create and compile vertex shader.
GLDEBUG(fragShader = glCreateShader(GL_FRAGMENT_SHADER));
GLDEBUG(glShaderSource(fragShader, 2, fragSource, NULL));
GLDEBUG(glCompileShader(fragShader));
// Report any compile issues to stderr
logLength = 0; // In case glGetShaderiv fails
GLDEBUG(glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetShaderInfoLog fails
GLDEBUG(glGetShaderInfoLog(fragShader, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to compile fragment shader: %s\nShader compile log:\n%s", szKey, log);
free(log);
}
// Attach vertex shader to program.
GLDEBUG(glAttachShader(m_iProgram, vertexShader));
// Attach fragment shader to program.
GLDEBUG(glAttachShader(m_iProgram, fragShader));
// Bind attribute locations.
// This needs to be done prior to linking.
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_VERTEX, "vertex_position"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_NORMAL, "vertex_normal"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TANGENT, "vertex_tangent"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TEXUVA, "vertex_uv"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TEXUVB, "vertex_lightmap_uv"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_BONEINDEXES, "bone_indexes"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, "bone_weights"));
// Link program.
GLDEBUG(glLinkProgram(m_iProgram));
GLint link_success = GL_FALSE;
GLDEBUG(glGetProgramiv(m_iProgram, GL_LINK_STATUS, &link_success));
if(link_success != GL_TRUE) {
// Report any linking issues to stderr
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to link shader program: %s", szKey);
logLength = 0; // In case glGetProgramiv fails
GLDEBUG(glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetProgramInfoLog fails
GLDEBUG(glGetProgramInfoLog(m_iProgram, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Program link log:\n%s", log);
free(log);
}
GLDEBUG(glDeleteProgram(m_iProgram));
m_iProgram = 0;
} else {
// Get uniform locations
for(int i=0; i < KRENGINE_NUM_UNIFORMS; i++ ){
GLDEBUG(m_uniforms[i] = glGetUniformLocation(m_iProgram, KRENGINE_UNIFORM_NAMES[i]));
m_uniform_value_index[i] = -1;
}
}
// Release vertex and fragment shaders.
if (vertexShader) {
GLDEBUG(glDeleteShader(vertexShader));
}
if (fragShader) {
GLDEBUG(glDeleteShader(fragShader));
}
}
KRPipeline::~KRPipeline() {
if(m_iProgram) {
GLDEBUG(glDeleteProgram(m_iProgram));
if(getContext().getPipelineManager()->m_active_pipeline == this) {
getContext().getPipelineManager()->m_active_pipeline = NULL;
}
}
}
void KRPipeline::setUniform(int location, float value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_float.size();
m_uniform_value_float.push_back(value);
} else if(m_uniform_value_float[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_float[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform1f(m_uniforms[location], value));
}
}
}
void KRPipeline::setUniform(int location, int value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_int.size();
m_uniform_value_int.push_back(value);
} else if(m_uniform_value_int[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_int[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform1i(m_uniforms[location], value));
}
}
}
void KRPipeline::setUniform(int location, const Vector2 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_vector2.size();
m_uniform_value_vector2.push_back(value);
} else if(m_uniform_value_vector2[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector2[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform2f(m_uniforms[location], value.x, value.y));
}
}
}
void KRPipeline::setUniform(int location, const Vector3 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_vector3.size();
m_uniform_value_vector3.push_back(value);
} else if(m_uniform_value_vector3[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector3[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform3f(m_uniforms[location], value.x, value.y, value.z));
}
}
}
void KRPipeline::setUniform(int location, const Vector4 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_vector4.size();
m_uniform_value_vector4.push_back(value);
} else if(m_uniform_value_vector4[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector4[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform4f(m_uniforms[location], value.x, value.y, value.z, value.w));
}
}
}
void KRPipeline::setUniform(int location, const Matrix4 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = (int)m_uniform_value_mat4.size();
m_uniform_value_mat4.push_back(value);
} else if(m_uniform_value_mat4[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_mat4[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniformMatrix4fv(m_uniforms[location], 1, GL_FALSE, value.c));
}
}
}
bool KRPipeline::bind(KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color) {
if(m_iProgram == 0) {
return false;
}
bool shander_changed = false;
if(getContext().getPipelineManager()->m_active_pipeline != this) {
getContext().getPipelineManager()->m_active_pipeline = this;
GLDEBUG(glUseProgram(m_iProgram));
shander_changed = true;
}
setUniform(KRENGINE_UNIFORM_ABSOLUTE_TIME, getContext().getAbsoluteTime());
int light_directional_count = 0;
//int light_point_count = 0;
//int light_spot_count = 0;
// TODO - Need to support multiple lights and more light types in forward rendering
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
for(std::vector<KRDirectionalLight *>::const_iterator light_itr=directional_lights.begin(); light_itr != directional_lights.end(); light_itr++) {
KRDirectionalLight *directional_light = (*light_itr);
if(light_directional_count == 0) {
int cShadowBuffers = directional_light->getShadowBufferCount();
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 3, directional_light->getShadowTextures()[0])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(3, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(3, GL_CLAMP_TO_EDGE);
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1 && camera.settings.m_cShadowBuffers > 1) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 4, directional_light->getShadowTextures()[1])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(4, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(4, GL_CLAMP_TO_EDGE);
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2 && camera.settings.m_cShadowBuffers > 2) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 5, directional_light->getShadowTextures()[2])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(5, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(5, GL_CLAMP_TO_EDGE);
}
Matrix4 matBias;
matBias.translate(1.0, 1.0, 1.0);
matBias.scale(0.5);
for(int iShadow=0; iShadow < cShadowBuffers; iShadow++) {
setUniform(KRENGINE_UNIFORM_SHADOWMVP1 + iShadow, matModel * directional_light->getShadowViewports()[iShadow].getViewProjectionMatrix() * matBias);
}
if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
// Bind the light direction vector
Vector3 lightDirObject = Matrix4::Dot(inverseModelMatrix, directional_light->getWorldLightDirection());
lightDirObject.normalize();
setUniform(KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE, lightDirObject);
}
}
light_directional_count++;
}
//light_point_count = point_lights.size();
//light_spot_count = spot_lights.size();
}
if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) {
// Transform location of camera to object space for calculation of specular halfVec
Vector3 cameraPosObject = Matrix4::Dot(inverseModelMatrix, viewport.getCameraPosition());
setUniform(KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE, cameraPosObject);
}
}
if(m_uniforms[KRENGINE_UNIFORM_MVP] != -1 || m_uniforms[KRPipeline::KRENGINE_UNIFORM_INVMVP] != -1) {
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
Matrix4 mvpMatrix = matModel * viewport.getViewProjectionMatrix();
setUniform(KRENGINE_UNIFORM_MVP, mvpMatrix);
if(m_uniforms[KRPipeline::KRENGINE_UNIFORM_INVMVP] != -1) {
setUniform(KRPipeline::KRENGINE_UNIFORM_INVMVP, Matrix4::Invert(mvpMatrix));
}
}
if(m_uniforms[KRPipeline::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1 || m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1 || m_uniforms[KRPipeline::KRENGINE_UNIFORM_MODEL_VIEW] != -1) {
Matrix4 matModelView = matModel * viewport.getViewMatrix();
setUniform(KRENGINE_UNIFORM_MODEL_VIEW, matModelView);
if(m_uniforms[KRPipeline::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1) {
Vector3 view_space_model_origin = Matrix4::Dot(matModelView, Vector3::Zero()); // Origin point of model space is the light source position. No perspective, so no w divide required
setUniform(KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN, view_space_model_origin);
}
if(m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1) {
Matrix4 matModelViewInverseTranspose = matModelView;
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
setUniform(KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE, matModelViewInverseTranspose);
}
}
if(m_uniforms[KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE] != -1) {
Matrix4 matModelInverseTranspose = matModel;
matModelInverseTranspose.transpose();
matModelInverseTranspose.invert();
setUniform(KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE, matModelInverseTranspose);
}
if(m_uniforms[KRPipeline::KRENGINE_UNIFORM_INVP] != -1) {
setUniform(KRENGINE_UNIFORM_INVP, viewport.getInverseProjectionMatrix());
}
if(m_uniforms[KRPipeline::KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE] != -1) {
Matrix4 matInvMVPNoTranslate = matModel * viewport.getViewMatrix();;
// Remove the translation
matInvMVPNoTranslate.getPointer()[3] = 0;
matInvMVPNoTranslate.getPointer()[7] = 0;
matInvMVPNoTranslate.getPointer()[11] = 0;
matInvMVPNoTranslate.getPointer()[12] = 0;
matInvMVPNoTranslate.getPointer()[13] = 0;
matInvMVPNoTranslate.getPointer()[14] = 0;
matInvMVPNoTranslate.getPointer()[15] = 1.0;
matInvMVPNoTranslate = matInvMVPNoTranslate * viewport.getProjectionMatrix();
matInvMVPNoTranslate.invert();
setUniform(KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE, matInvMVPNoTranslate);
}
setUniform(KRENGINE_UNIFORM_MODEL_MATRIX, matModel);
if(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX] != -1) {
setUniform(KRENGINE_UNIFORM_PROJECTION_MATRIX, viewport.getProjectionMatrix());
}
if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT] != -1) {
setUniform(KRENGINE_UNIFORM_VIEWPORT, Vector4::Create(
(GLfloat)0.0,
(GLfloat)0.0,
(GLfloat)viewport.getSize().x,
(GLfloat)viewport.getSize().y
)
);
}
if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE] != -1) {
setUniform(KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE, camera.getDownsample());
}
// Rim highlighting parameters
setUniform(KRENGINE_UNIFORM_RIM_COLOR, rim_color);
setUniform(KRENGINE_UNIFORM_RIM_POWER, rim_power);
// Fade parameters
setUniform(KRENGINE_UNIFORM_FADE_COLOR, fade_color);
// Fog parameters
setUniform(KRENGINE_UNIFORM_FOG_NEAR, camera.settings.fog_near);
setUniform(KRENGINE_UNIFORM_FOG_FAR, camera.settings.fog_far);
setUniform(KRENGINE_UNIFORM_FOG_DENSITY, camera.settings.fog_density);
setUniform(KRENGINE_UNIFORM_FOG_COLOR, camera.settings.fog_color);
if(m_uniforms[KRENGINE_UNIFORM_FOG_SCALE] != -1) {
setUniform(KRENGINE_UNIFORM_FOG_SCALE, 1.0f / (camera.settings.fog_far - camera.settings.fog_near));
}
if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL] != -1) {
setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL, -camera.settings.fog_density * 1.442695f); // -fog_density / log(2)
}
if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED] != -1) {
setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED, (float)(-camera.settings.fog_density * camera.settings.fog_density * 1.442695)); // -fog_density * fog_density / log(2)
}
// Sets the diffuseTexture variable to the first texture unit
setUniform(KRENGINE_UNIFORM_DIFFUSETEXTURE, 0);
// Sets the specularTexture variable to the second texture unit
setUniform(KRENGINE_UNIFORM_SPECULARTEXTURE, 1);
// Sets the normalTexture variable to the third texture unit
setUniform(KRENGINE_UNIFORM_NORMALTEXTURE, 2);
// Sets the shadowTexture variable to the fourth texture unit
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE1, 3);
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE2, 4);
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE3, 5);
setUniform(KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE, 4);
setUniform(KRENGINE_UNIFORM_LIGHTMAPTEXTURE, 5);
setUniform(KRENGINE_UNIFORM_GBUFFER_FRAME, 6);
setUniform(KRENGINE_UNIFORM_GBUFFER_DEPTH, 7); // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass
setUniform(KRENGINE_UNIFORM_REFLECTIONTEXTURE, 7); // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering
setUniform(KRENGINE_UNIFORM_DEPTH_FRAME, 0);
setUniform(KRENGINE_UNIFORM_RENDER_FRAME, 1);
setUniform(KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME, 2);
#if defined(DEBUG)
if(shander_changed) { // FINDME!! KIP!! HACK!!
GLint logLength;
GLint validate_status = GL_FALSE;
GLDEBUG(glValidateProgram(m_iProgram));
GLDEBUG(glGetProgramiv(m_iProgram, GL_VALIDATE_STATUS, &validate_status));
if(validate_status != GL_TRUE) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to validate shader program: %s", m_szKey);
logLength = 0; // In case glGetProgramiv fails
GLDEBUG(glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetProgramInfoLog fails
GLDEBUG(glGetProgramInfoLog(m_iProgram, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Program validate log:\n%s", log);
free(log);
}
return false;
}
}
#endif
return true;
}
const char *KRPipeline::getKey() const {
return m_szKey;
}

161
kraken/KRPipeline.h Normal file
View File

@@ -0,0 +1,161 @@
//
// KRPipeline.h
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRPIPELINE_H
#define KRPIPELINE_H
#include "KREngine-common.h"
#include "KRPipeline.h"
#include "KRCamera.h"
#include "KRNode.h"
#include "KRViewport.h"
class KRPipeline : public KRContextObject {
public:
KRPipeline(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource);
virtual ~KRPipeline();
const char *getKey() const;
bool bind(KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color);
enum {
KRENGINE_UNIFORM_MATERIAL_AMBIENT = 0,
KRENGINE_UNIFORM_MATERIAL_DIFFUSE,
KRENGINE_UNIFORM_MATERIAL_SPECULAR,
KRENGINE_UNIFORM_MATERIAL_REFLECTION,
KRENGINE_UNIFORM_MATERIAL_ALPHA,
KRENGINE_UNIFORM_MATERIAL_SHININESS,
KRENGINE_UNIFORM_LIGHT_POSITION,
KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE,
KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE,
KRENGINE_UNIFORM_LIGHT_COLOR,
KRENGINE_UNIFORM_LIGHT_DECAY_START,
KRENGINE_UNIFORM_LIGHT_CUTOFF,
KRENGINE_UNIFORM_LIGHT_INTENSITY,
KRENGINE_UNIFORM_FLARE_SIZE,
KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN,
KRENGINE_UNIFORM_MVP,
KRENGINE_UNIFORM_INVP,
KRENGINE_UNIFORM_INVMVP,
KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE,
KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE,
KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE,
KRENGINE_UNIFORM_MODEL_VIEW,
KRENGINE_UNIFORM_MODEL_MATRIX,
KRENGINE_UNIFORM_PROJECTION_MATRIX,
KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE,
KRENGINE_UNIFORM_VIEWPORT,
KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE,
KRENGINE_UNIFORM_DIFFUSETEXTURE,
KRENGINE_UNIFORM_SPECULARTEXTURE,
KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE,
KRENGINE_UNIFORM_REFLECTIONTEXTURE,
KRENGINE_UNIFORM_NORMALTEXTURE,
KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE,
KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE,
KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE,
KRENGINE_UNIFORM_NORMALTEXTURE_SCALE,
KRENGINE_UNIFORM_AMBIENTTEXTURE_SCALE,
KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET,
KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET,
KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET,
KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET,
KRENGINE_UNIFORM_AMBIENTTEXTURE_OFFSET,
KRENGINE_UNIFORM_SHADOWMVP1,
KRENGINE_UNIFORM_SHADOWMVP2,
KRENGINE_UNIFORM_SHADOWMVP3,
KRENGINE_UNIFORM_SHADOWTEXTURE1,
KRENGINE_UNIFORM_SHADOWTEXTURE2,
KRENGINE_UNIFORM_SHADOWTEXTURE3,
KRENGINE_UNIFORM_LIGHTMAPTEXTURE,
KRENGINE_UNIFORM_GBUFFER_FRAME,
KRENGINE_UNIFORM_GBUFFER_DEPTH,
KRENGINE_UNIFORM_DEPTH_FRAME,
KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME,
KRENGINE_UNIFORM_RENDER_FRAME,
KRENGINE_UNIFORM_ABSOLUTE_TIME,
KRENGINE_UNIFORM_FOG_NEAR,
KRENGINE_UNIFORM_FOG_FAR,
KRENGINE_UNIFORM_FOG_DENSITY,
KRENGINE_UNIFORM_FOG_COLOR,
KRENGINE_UNIFORM_FOG_SCALE,
KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL,
KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED,
KRENGINE_UNIFORM_SLICE_DEPTH_SCALE,
KRENGINE_UNIFORM_PARTICLE_ORIGIN,
KRENGINE_UNIFORM_BONE_TRANSFORMS,
KRENGINE_UNIFORM_RIM_COLOR,
KRENGINE_UNIFORM_RIM_POWER,
KRENGINE_UNIFORM_FADE_COLOR,
KRENGINE_NUM_UNIFORMS
};
/*
typedef enum {
KRENGINE_UNIFORM_TYPE_UNKNOWN,
KRENGINE_UNIFORM_TYPE_FLOAT,
KRENGINE_UNIFORM_TYPE_INT,
KRENGINE_UNIFORM_TYPE_VECTOR2,
KRENGINE_UNIFORM_TYPE_VECTOR3,
KRENGINE_UNIFORM_TYPE_VECTOR4,
KRENGINE_UNIFORM_TYPE_MAT4
} uniform_type_t;
uniform_type_t m_uniform_type[KRENGINE_NUM_UNIFORMS];
*/
static const char *KRENGINE_UNIFORM_NAMES[];
GLint m_uniforms[KRENGINE_NUM_UNIFORMS];
int m_uniform_value_index[KRENGINE_NUM_UNIFORMS];
std::vector<float> m_uniform_value_float;
std::vector<int> m_uniform_value_int;
std::vector<Vector2> m_uniform_value_vector2;
std::vector<Vector3> m_uniform_value_vector3;
std::vector<Vector4> m_uniform_value_vector4;
std::vector<Matrix4> m_uniform_value_mat4;
char m_szKey[256];
void setUniform(int location, float value);
void setUniform(int location, int value);
void setUniform(int location, const Vector2 &value);
void setUniform(int location, const Vector3 &value);
void setUniform(int location, const Vector4 &value);
void setUniform(int location, const Matrix4 &value);
private:
GLuint m_iProgram;
};
#endif

View File

@@ -0,0 +1,273 @@
//
// KRPipelineManager.cpp
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRPipelineManager.h"
#include "KRLight.h"
#include "KRDirectionalLight.h"
#include "KRSpotLight.h"
#include "KRPointLight.h"
#ifndef ANDROID
#include "glslang/Public/ShaderLang.h"
#endif
using namespace std;
KRPipelineManager::KRPipelineManager(KRContext &context) : KRContextObject(context) {
m_active_pipeline = NULL;
#ifndef ANDROID
bool success = glslang::InitializeProcess();
if (success) {
printf("GLSLang Initialized.\n");
}
else {
printf("Failed to initialize GLSLang.\n");
}
#endif // ANDROID
}
KRPipelineManager::~KRPipelineManager() {
#ifndef ANDROID
glslang::FinalizeProcess();
#endif // ANDROID
}
KRPipeline *KRPipelineManager::getPipeline(const std::string &pipeline_name, KRCamera *pCamera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor) {
int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader
int light_directional_count = 0;
int light_point_count = 0;
int light_spot_count = 0;
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
light_directional_count = (int)directional_lights.size();
light_point_count = (int)point_lights.size();
light_spot_count = (int)spot_lights.size();
for(std::vector<KRDirectionalLight *>::const_iterator light_itr=directional_lights.begin(); light_itr != directional_lights.end(); light_itr++) {
KRDirectionalLight *directional_light =(*light_itr);
iShadowQuality = directional_light->getShadowBufferCount();
}
}
if(iShadowQuality > pCamera->settings.m_cShadowBuffers) {
iShadowQuality = pCamera->settings.m_cShadowBuffers;
}
bool bFadeColorEnabled = pCamera->getFadeColor().w >= 0.0f;
std::pair<std::string, std::vector<int> > key;
key.first = pipeline_name;
key.second.push_back(light_directional_count);
key.second.push_back(light_point_count);
key.second.push_back(light_spot_count);
key.second.push_back(pCamera->settings.fog_type);
key.second.push_back(pCamera->settings.bEnablePerPixel);
key.second.push_back(bAlphaTest);
key.second.push_back(bAlphaBlend);
key.second.push_back(bDiffuseMap);
key.second.push_back(bNormalMap);
key.second.push_back(bSpecMap);
key.second.push_back(bReflectionMap);
key.second.push_back(bone_count);
key.second.push_back(bSpecMap);
key.second.push_back(bReflectionMap);
key.second.push_back(bReflectionCubeMap);
key.second.push_back(pCamera->settings.bDebugPSSM);
key.second.push_back(iShadowQuality);
key.second.push_back(pCamera->settings.bEnableAmbient);
key.second.push_back(pCamera->settings.bEnableDiffuse);
key.second.push_back(pCamera->settings.bEnableSpecular);
key.second.push_back(bLightMap);
key.second.push_back(bDiffuseMapScale);
key.second.push_back(bSpecMapScale);
key.second.push_back(bReflectionMapScale);
key.second.push_back(bNormalMapScale);
key.second.push_back(bDiffuseMapOffset);
key.second.push_back(bSpecMapOffset);
key.second.push_back(bReflectionMapOffset);
key.second.push_back(bNormalMapOffset);
key.second.push_back(pCamera->settings.volumetric_environment_enable);
key.second.push_back(pCamera->settings.volumetric_environment_downsample != 0);
key.second.push_back(renderPass);
key.second.push_back(pCamera->settings.dof_quality);
key.second.push_back(pCamera->settings.bEnableFlash);
key.second.push_back(pCamera->settings.bEnableVignette);
key.second.push_back((int)(pCamera->settings.dof_depth * 1000.0f));
key.second.push_back((int)(pCamera->settings.dof_falloff * 1000.0f));
key.second.push_back((int)(pCamera->settings.flash_depth * 1000.0f));
key.second.push_back((int)(pCamera->settings.flash_falloff * 1000.0f));
key.second.push_back((int)(pCamera->settings.flash_intensity * 1000.0f));
key.second.push_back((int)(pCamera->settings.vignette_radius * 1000.0f));
key.second.push_back((int)(pCamera->settings.vignette_falloff * 1000.0f));
key.second.push_back(bRimColor);
key.second.push_back(bFadeColorEnabled);
KRPipeline *pPipeline = m_pipelines[key];
if(pPipeline == NULL) {
if(m_pipelines.size() > KRContext::KRENGINE_MAX_PIPELINE_HANDLES) {
// Keep the size of the pipeline cache reasonable
std::map<std::pair<std::string, std::vector<int> > , KRPipeline *>::iterator itr = m_pipelines.begin();
delete (*itr).second;
m_pipelines.erase(itr);
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Swapping pipelines...\n");
}
stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10);
#if TARGET_OS_IPHONE
#else
stream << "\n#version 150";
stream << "\n#define lowp";
stream << "\n#define mediump";
stream << "\n#define highp";
#endif
stream << "\n#define LIGHT_DIRECTIONAL_COUNT " << light_directional_count;
stream << "\n#define LIGHT_POINT_COUNT " << light_point_count;
stream << "\n#define LIGHT_SPOT_COUNT " << light_spot_count;
stream << "\n#define BONE_COUNT " << bone_count;
stream << "\n#define HAS_DIFFUSE_MAP " << (bDiffuseMap ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_SCALE " << (bDiffuseMapScale ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_OFFSET " << (bDiffuseMapOffset ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP " << (bSpecMap ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_SCALE " << (bSpecMapScale ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_OFFSET " << (bSpecMapOffset ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP " << (bNormalMap ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_SCALE " << (bNormalMapScale ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_OFFSET " << (bNormalMapOffset ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP " << (bReflectionMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_SCALE " << (bReflectionMapScale ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_OFFSET " << (bReflectionMapOffset ? "1" : "0");
stream << "\n#define HAS_LIGHT_MAP " << (bLightMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_CUBE_MAP " << (bReflectionCubeMap ? "1" : "0");
stream << "\n#define ALPHA_TEST " << (bAlphaTest ? "1" : "0");
stream << "\n#define ALPHA_BLEND " << (bAlphaBlend ? "1" : "0");
stream << "\n#define ENABLE_PER_PIXEL " << (pCamera->settings.bEnablePerPixel ? "1" : "0");
stream << "\n#define DEBUG_PSSM " << (pCamera->settings.bDebugPSSM ? "1" : "0");
stream << "\n#define SHADOW_QUALITY " << iShadowQuality;
stream << "\n#define ENABLE_AMBIENT " << (pCamera->settings.bEnableAmbient ? "1" : "0");
stream << "\n#define ENABLE_DIFFUSE " << (pCamera->settings.bEnableDiffuse ? "1" : "0");
stream << "\n#define ENABLE_SPECULAR " << (pCamera->settings.bEnableSpecular ? "1" : "0");
stream << "\n#define ENABLE_RIM_COLOR " << (bRimColor ? "1" : "0");
stream << "\n#define ENABLE_FADE_COLOR " << (bFadeColorEnabled ? "1" : "0");
stream << "\n#define FOG_TYPE " << pCamera->settings.fog_type;
switch(renderPass) {
case KRNode::RENDER_PASS_DEFERRED_GBUFFER:
stream << "\n#define GBUFFER_PASS " << 1;
break;
case KRNode::RENDER_PASS_DEFERRED_LIGHTS:
stream << "\n#define GBUFFER_PASS " << 2;
break;
case KRNode::RENDER_PASS_DEFERRED_OPAQUE:
stream << "\n#define GBUFFER_PASS " << 3;
break;
default:
stream << "\n#define GBUFFER_PASS " << 0;
break;
}
stream << "\n#define DOF_QUALITY " << pCamera->settings.dof_quality;
stream << "\n#define ENABLE_FLASH " << (pCamera->settings.bEnableFlash ? "1" : "0");
stream << "\n#define ENABLE_VIGNETTE " << (pCamera->settings.bEnableVignette ? "1" : "0");
stream << "\n#define VOLUMETRIC_ENVIRONMENT_DOWNSAMPLED " << (pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0 ? "1" : "0");
stream.setf(ios::fixed,ios::floatfield);
stream.precision(std::numeric_limits<long double>::digits10);
stream << "\n#define DOF_DEPTH " << pCamera->settings.dof_depth;
stream << "\n#define DOF_FALLOFF " << pCamera->settings.dof_falloff;
stream << "\n#define FLASH_DEPTH " << pCamera->settings.flash_depth;
stream << "\n#define FLASH_FALLOFF " << pCamera->settings.flash_falloff;
stream << "\n#define FLASH_INTENSITY " << pCamera->settings.flash_intensity;
stream << "\n#define VIGNETTE_RADIUS " << pCamera->settings.vignette_radius;
stream << "\n#define VIGNETTE_FALLOFF " << pCamera->settings.vignette_falloff;
stream << "\n";
std::string options = stream.str();
KRSourceManager *sourceManager = m_pContext->getSourceManager();
KRSource *vertSource = sourceManager->get(pipeline_name.c_str(), "vert");
KRSource *fragSource = sourceManager->get(pipeline_name.c_str(), "frag");
if(vertSource == nullptr) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Vertex Shader Missing: %s", pipeline_name.c_str());
}
if(fragSource == nullptr) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Fragment Shader Missing: %s", pipeline_name.c_str());
}
Vector4 fade_color = pCamera->getFadeColor();
char szKey[256];
sprintf(szKey, "%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f", light_directional_count, light_point_count, light_spot_count, bone_count, pCamera->settings.fog_type, pCamera->settings.bEnablePerPixel,bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->settings.bDebugPSSM, iShadowQuality, pCamera->settings.bEnableAmbient, pCamera->settings.bEnableDiffuse, pCamera->settings.bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0, renderPass, pipeline_name.c_str(),pCamera->settings.dof_quality,pCamera->settings.bEnableFlash,pCamera->settings.bEnableVignette,pCamera->settings.dof_depth,pCamera->settings.dof_falloff,pCamera->settings.flash_depth,pCamera->settings.flash_falloff,pCamera->settings.flash_intensity,pCamera->settings.vignette_radius,pCamera->settings.vignette_falloff, fade_color.x, fade_color.y, fade_color.z, fade_color.w);
pPipeline = new KRPipeline(getContext(), szKey, options, vertSource->getData()->getString(), fragSource->getData()->getString());
m_pipelines[key] = pPipeline;
}
return pPipeline;
}
bool KRPipelineManager::selectPipeline(const std::string &pipeline_name, KRCamera &camera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRViewport &viewport, const Matrix4 &matModel, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color)
{
KRPipeline *pPipeline = getPipeline(pipeline_name, &camera, point_lights, directional_lights, spot_lights, bone_count, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, bDiffuseMapScale, bSpecMapScale, bNormalMapScale, bReflectionMapScale, bDiffuseMapOffset, bSpecMapOffset, bNormalMapOffset, bReflectionMapOffset, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
return selectPipeline(camera, pPipeline, viewport, matModel, point_lights, directional_lights, spot_lights, bone_count, renderPass, rim_color, rim_power, fade_color);
}
bool KRPipelineManager::selectPipeline(KRCamera &camera, KRPipeline *pPipeline, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color)
{
if(pPipeline) {
return pPipeline->bind(camera, viewport, matModel, point_lights, directional_lights, spot_lights, renderPass, rim_color, rim_power, fade_color);
} else {
return false;
}
}
size_t KRPipelineManager::getPipelineHandlesUsed() {
return m_pipelines.size();
}

View File

@@ -0,0 +1,69 @@
//
// KRPipelineManager.h
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KREngine-common.h"
#include "KRCamera.h"
#include "KRDataBlock.h"
#include "KRNode.h"
using std::map;
using std::vector;
#include "KRPipeline.h"
#ifndef KRPIPELINEMANAGER_H
#define KRPIPELINEMANAGER_H
class KRPipeline;
class KRCamera;
class KRPipelineManager : public KRContextObject {
public:
KRPipelineManager(KRContext &context);
virtual ~KRPipelineManager();
KRPipeline *getPipeline(const std::string &pipeline_name, KRCamera *pCamera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor = false);
bool selectPipeline(KRCamera &camera, KRPipeline *pPipeline, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color);
bool selectPipeline(const std::string &pipeline_name, KRCamera &camera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRViewport &viewport, const Matrix4 &matModel, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color);
size_t getPipelineHandlesUsed();
KRPipeline *m_active_pipeline;
private:
std::map<std::pair<std::string, std::vector<int> >, KRPipeline *> m_pipelines;
};
#endif

View File

@@ -1,226 +1,226 @@
// //
// KRPointLight.cpp // KRPointLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRPointLight.h" #include "KRPointLight.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name) KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
m_sphereVertices = NULL; m_sphereVertices = NULL;
m_cVertices = 0; m_cVertices = 0;
} }
KRPointLight::~KRPointLight() KRPointLight::~KRPointLight()
{ {
if(m_sphereVertices) { if(m_sphereVertices) {
delete m_sphereVertices; delete m_sphereVertices;
m_cVertices = 0; m_cVertices = 0;
} }
} }
std::string KRPointLight::getElementName() { std::string KRPointLight::getElementName() {
return "point_light"; return "point_light";
} }
AABB KRPointLight::getBounds() { AABB KRPointLight::getBounds() {
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
if(influence_radius < m_flareOcclusionSize) { if(influence_radius < m_flareOcclusionSize) {
influence_radius = m_flareOcclusionSize; influence_radius = m_flareOcclusionSize;
} }
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix()); return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
} }
void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRPointLight::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred; bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) { if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
// Lights are rendered on the second pass of the deferred renderer // Lights are rendered on the second pass of the deferred renderer
std::vector<KRPointLight *> this_light; std::vector<KRPointLight *> this_light;
this_light.push_back(this); this_light.push_back(this);
Vector3 light_position = getLocalTranslation(); Vector3 light_position = getLocalTranslation();
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
Matrix4 sphereModelMatrix = Matrix4(); Matrix4 sphereModelMatrix = Matrix4();
sphereModelMatrix.scale(influence_radius); sphereModelMatrix.scale(influence_radius);
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z); sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position); Vector3 view_light_position = Matrix4::Dot(viewport.getViewMatrix(), light_position);
bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ()); bool bInsideLight = view_light_position.sqrMagnitude() <= (influence_radius + pCamera->settings.getPerspectiveNearZ()) * (influence_radius + pCamera->settings.getPerspectiveNearZ());
KRShader *pShader = getContext().getShaderManager()->getShader(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline(bVisualize ? "visualize_overlay" : (bInsideLight ? "light_point_inside" : "light_point"), pCamera, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart()); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
if(bVisualize) { if(bVisualize) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
} }
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
if(bInsideLight) { if(bInsideLight) {
// Disable z-buffer test // Disable z-buffer test
GLDEBUG(glDisable(GL_DEPTH_TEST)); GLDEBUG(glDisable(GL_DEPTH_TEST));
// Render a full screen quad // Render a full screen quad
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} else { } else {
#if GL_OES_vertex_array_object #if GL_OES_vertex_array_object
GLDEBUG(glBindVertexArrayOES(0)); GLDEBUG(glBindVertexArrayOES(0));
#endif #endif
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX); m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
// Render sphere of light's influence // Render sphere of light's influence
generateMesh(); generateMesh();
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices)); GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices)); GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
} }
} }
if(bVisualize) { if(bVisualize) {
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
} }
void KRPointLight::generateMesh() { void KRPointLight::generateMesh() {
// Create a triangular facet approximation to a sphere // Create a triangular facet approximation to a sphere
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/ // Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
int iterations = 3; int iterations = 3;
int facet_count = pow(4, iterations) * 8; int facet_count = (int)(pow(4, iterations) * 8);
if(m_cVertices != facet_count * 3) { if(m_cVertices != facet_count * 3) {
if(m_sphereVertices) { if(m_sphereVertices) {
free(m_sphereVertices); free(m_sphereVertices);
m_sphereVertices = NULL; m_sphereVertices = NULL;
} }
m_cVertices = facet_count * 3; m_cVertices = facet_count * 3;
class Facet3 { class Facet3 {
public: public:
Facet3() { Facet3() {
} }
~Facet3() { ~Facet3() {
} }
Vector3 p1; Vector3 p1;
Vector3 p2; Vector3 p2;
Vector3 p3; Vector3 p3;
}; };
std::vector<Facet3> f = std::vector<Facet3>(facet_count); std::vector<Facet3> f = std::vector<Facet3>(facet_count);
int i,it; int i,it;
float a; float a;
Vector3 p[6] = { Vector3 p[6] = {
Vector3::Create(0,0,1), Vector3::Create(0,0,1),
Vector3::Create(0,0,-1), Vector3::Create(0,0,-1),
Vector3::Create(-1,-1,0), Vector3::Create(-1,-1,0),
Vector3::Create(1,-1,0), Vector3::Create(1,-1,0),
Vector3::Create(1,1,0), Vector3::Create(1,1,0),
Vector3::Create(-1,1,0) Vector3::Create(-1,1,0)
}; };
Vector3 pa,pb,pc; Vector3 pa,pb,pc;
int nt = 0,ntold; int nt = 0,ntold;
/* Create the level 0 object */ /* Create the level 0 object */
a = 1.0f / sqrtf(2.0f); a = 1.0f / sqrtf(2.0f);
for (i=0;i<6;i++) { for (i=0;i<6;i++) {
p[i].x *= a; p[i].x *= a;
p[i].y *= a; p[i].y *= a;
} }
f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4]; f[0].p1 = p[0]; f[0].p2 = p[3]; f[0].p3 = p[4];
f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5]; f[1].p1 = p[0]; f[1].p2 = p[4]; f[1].p3 = p[5];
f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2]; f[2].p1 = p[0]; f[2].p2 = p[5]; f[2].p3 = p[2];
f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3]; f[3].p1 = p[0]; f[3].p2 = p[2]; f[3].p3 = p[3];
f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3]; f[4].p1 = p[1]; f[4].p2 = p[4]; f[4].p3 = p[3];
f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4]; f[5].p1 = p[1]; f[5].p2 = p[5]; f[5].p3 = p[4];
f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5]; f[6].p1 = p[1]; f[6].p2 = p[2]; f[6].p3 = p[5];
f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2]; f[7].p1 = p[1]; f[7].p2 = p[3]; f[7].p3 = p[2];
nt = 8; nt = 8;
/* Bisect each edge and move to the surface of a unit sphere */ /* Bisect each edge and move to the surface of a unit sphere */
for (it=0;it<iterations;it++) { for (it=0;it<iterations;it++) {
ntold = nt; ntold = nt;
for (i=0;i<ntold;i++) { for (i=0;i<ntold;i++) {
pa.x = (f[i].p1.x + f[i].p2.x) / 2; pa.x = (f[i].p1.x + f[i].p2.x) / 2;
pa.y = (f[i].p1.y + f[i].p2.y) / 2; pa.y = (f[i].p1.y + f[i].p2.y) / 2;
pa.z = (f[i].p1.z + f[i].p2.z) / 2; pa.z = (f[i].p1.z + f[i].p2.z) / 2;
pb.x = (f[i].p2.x + f[i].p3.x) / 2; pb.x = (f[i].p2.x + f[i].p3.x) / 2;
pb.y = (f[i].p2.y + f[i].p3.y) / 2; pb.y = (f[i].p2.y + f[i].p3.y) / 2;
pb.z = (f[i].p2.z + f[i].p3.z) / 2; pb.z = (f[i].p2.z + f[i].p3.z) / 2;
pc.x = (f[i].p3.x + f[i].p1.x) / 2; pc.x = (f[i].p3.x + f[i].p1.x) / 2;
pc.y = (f[i].p3.y + f[i].p1.y) / 2; pc.y = (f[i].p3.y + f[i].p1.y) / 2;
pc.z = (f[i].p3.z + f[i].p1.z) / 2; pc.z = (f[i].p3.z + f[i].p1.z) / 2;
pa.normalize(); pa.normalize();
pb.normalize(); pb.normalize();
pc.normalize(); pc.normalize();
f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++; f[nt].p1 = f[i].p1; f[nt].p2 = pa; f[nt].p3 = pc; nt++;
f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++; f[nt].p1 = pa; f[nt].p2 = f[i].p2; f[nt].p3 = pb; nt++;
f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++; f[nt].p1 = pb; f[nt].p2 = f[i].p3; f[nt].p3 = pc; nt++;
f[i].p1 = pa; f[i].p1 = pa;
f[i].p2 = pb; f[i].p2 = pb;
f[i].p3 = pc; f[i].p3 = pc;
} }
} }
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3); m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
assert(m_sphereVertices != NULL); assert(m_sphereVertices != NULL);
GLfloat *pDest = m_sphereVertices; GLfloat *pDest = m_sphereVertices;
for(int facet_index=0; facet_index < facet_count; facet_index++) { for(int facet_index=0; facet_index < facet_count; facet_index++) {
*pDest++ = f[facet_index].p1.x; *pDest++ = f[facet_index].p1.x;
*pDest++ = f[facet_index].p1.y; *pDest++ = f[facet_index].p1.y;
*pDest++ = f[facet_index].p1.z; *pDest++ = f[facet_index].p1.z;
*pDest++ = f[facet_index].p2.x; *pDest++ = f[facet_index].p2.x;
*pDest++ = f[facet_index].p2.y; *pDest++ = f[facet_index].p2.y;
*pDest++ = f[facet_index].p2.z; *pDest++ = f[facet_index].p2.z;
*pDest++ = f[facet_index].p3.x; *pDest++ = f[facet_index].p3.x;
*pDest++ = f[facet_index].p3.y; *pDest++ = f[facet_index].p3.y;
*pDest++ = f[facet_index].p3.z; *pDest++ = f[facet_index].p3.z;
} }
} }
} }

View File

@@ -1,204 +1,204 @@
// //
// KRRenderSettings.cpp // KRRenderSettings.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-20. // Created by Kearwood Gilbert on 2012-12-20.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRRenderSettings.h" #include "KRRenderSettings.h"
KRRenderSettings::KRRenderSettings() KRRenderSettings::KRRenderSettings()
{ {
siren_enable = true; siren_enable = true;
siren_enable_reverb = true; siren_enable_reverb = true;
siren_enable_hrtf = true; siren_enable_hrtf = true;
siren_reverb_max_length = 2.0f; siren_reverb_max_length = 2.0f;
m_enable_realtime_occlusion = false; m_enable_realtime_occlusion = false;
bShowShadowBuffer = false; bShowShadowBuffer = false;
bShowOctree = false; bShowOctree = false;
bShowDeferred = false; bShowDeferred = false;
bEnablePerPixel = true; bEnablePerPixel = true;
bEnableDiffuseMap = true; bEnableDiffuseMap = true;
bEnableNormalMap = true; bEnableNormalMap = true;
bEnableSpecMap = true; bEnableSpecMap = true;
bEnableReflectionMap = true; bEnableReflectionMap = true;
bEnableReflection = true; bEnableReflection = true;
bDebugPSSM = false; bDebugPSSM = false;
bEnableAmbient = true; bEnableAmbient = true;
bEnableDiffuse = true; bEnableDiffuse = true;
bEnableSpecular = true; bEnableSpecular = true;
bEnableLightMap = true; bEnableLightMap = true;
bEnableDeferredLighting = false; bEnableDeferredLighting = false;
max_anisotropy = 4.0f; max_anisotropy = 4.0f;
ambient_intensity = Vector3::Zero(); ambient_intensity = Vector3::Zero();
light_intensity = Vector3::One(); light_intensity = Vector3::One();
perspective_fov = 45.0f * D2R; perspective_fov = 45.0f * D2R;
perspective_nearz = 0.3f; // was 0.05f perspective_nearz = 0.3f; // was 0.05f
perspective_farz = 1000.0f; perspective_farz = 1000.0f;
dof_quality = 0; dof_quality = 0;
dof_depth = 0.05f; dof_depth = 0.05f;
dof_falloff = 0.05f; dof_falloff = 0.05f;
bEnableFlash = false; bEnableFlash = false;
flash_intensity = 1.0f; flash_intensity = 1.0f;
flash_depth = 0.7f; flash_depth = 0.7f;
flash_falloff = 0.5f; flash_falloff = 0.5f;
bEnableVignette = false; bEnableVignette = false;
vignette_radius = 0.4f; vignette_radius = 0.4f;
vignette_falloff = 1.0f; vignette_falloff = 1.0f;
m_cShadowBuffers = 0; m_cShadowBuffers = 0;
volumetric_environment_enable = false; volumetric_environment_enable = false;
volumetric_environment_downsample = 2; volumetric_environment_downsample = 2;
volumetric_environment_max_distance = 100.0f; volumetric_environment_max_distance = 100.0f;
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f; volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
volumetric_environment_intensity = 0.9f; volumetric_environment_intensity = 0.9f;
fog_near = 50.0f; fog_near = 50.0f;
fog_far = 500.0f; fog_far = 500.0f;
fog_density = 0.0005f; fog_density = 0.0005f;
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f); fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
fog_type = 0; fog_type = 0;
dust_particle_intensity = 0.25f; dust_particle_intensity = 0.25f;
dust_particle_enable = false; dust_particle_enable = false;
m_lodBias = 0.0f; m_lodBias = 0.0f;
debug_display = KRENGINE_DEBUG_DISPLAY_NONE; debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
} }
KRRenderSettings::~KRRenderSettings() KRRenderSettings::~KRRenderSettings()
{ {
} }
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s) KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
{ {
siren_enable = s.siren_enable; siren_enable = s.siren_enable;
siren_enable_reverb = s.siren_enable_reverb; siren_enable_reverb = s.siren_enable_reverb;
siren_enable_hrtf = s.siren_enable_hrtf; siren_enable_hrtf = s.siren_enable_hrtf;
siren_reverb_max_length = s.siren_reverb_max_length; siren_reverb_max_length = s.siren_reverb_max_length;
bEnablePerPixel = s.bEnablePerPixel; bEnablePerPixel = s.bEnablePerPixel;
bEnableDiffuseMap = s.bEnableDiffuseMap; bEnableDiffuseMap = s.bEnableDiffuseMap;
bEnableNormalMap = s.bEnableNormalMap; bEnableNormalMap = s.bEnableNormalMap;
bEnableSpecMap = s.bEnableSpecMap; bEnableSpecMap = s.bEnableSpecMap;
bEnableReflectionMap = s.bEnableReflectionMap; bEnableReflectionMap = s.bEnableReflectionMap;
bEnableReflection=s.bEnableReflection; bEnableReflection=s.bEnableReflection;
bEnableLightMap=s.bEnableLightMap; bEnableLightMap=s.bEnableLightMap;
bDebugPSSM=s.bDebugPSSM; bDebugPSSM=s.bDebugPSSM;
bShowShadowBuffer=s.bShowShadowBuffer; bShowShadowBuffer=s.bShowShadowBuffer;
bShowOctree=s.bShowOctree; bShowOctree=s.bShowOctree;
bShowDeferred=s.bShowDeferred; bShowDeferred=s.bShowDeferred;
bEnableAmbient=s.bEnableAmbient; bEnableAmbient=s.bEnableAmbient;
bEnableDiffuse=s.bEnableDiffuse; bEnableDiffuse=s.bEnableDiffuse;
bEnableSpecular=s.bEnableSpecular; bEnableSpecular=s.bEnableSpecular;
bEnableDeferredLighting=s.bEnableDeferredLighting; bEnableDeferredLighting=s.bEnableDeferredLighting;
light_intensity=s.light_intensity; light_intensity=s.light_intensity;
ambient_intensity=s.ambient_intensity; ambient_intensity=s.ambient_intensity;
perspective_fov=s.perspective_fov; perspective_fov=s.perspective_fov;
dof_quality=s.dof_quality; dof_quality=s.dof_quality;
dof_depth=s.dof_depth; dof_depth=s.dof_depth;
dof_falloff=s.dof_falloff; dof_falloff=s.dof_falloff;
bEnableFlash=s.bEnableFlash; bEnableFlash=s.bEnableFlash;
flash_intensity=s.flash_intensity; flash_intensity=s.flash_intensity;
flash_depth=s.flash_depth; flash_depth=s.flash_depth;
flash_falloff=s.flash_falloff; flash_falloff=s.flash_falloff;
bEnableVignette=s.bEnableVignette; bEnableVignette=s.bEnableVignette;
vignette_radius=s.vignette_radius; vignette_radius=s.vignette_radius;
vignette_falloff=s.vignette_falloff; vignette_falloff=s.vignette_falloff;
m_viewportSize=s.m_viewportSize; m_viewportSize=s.m_viewportSize;
m_cShadowBuffers=s.m_cShadowBuffers; m_cShadowBuffers=s.m_cShadowBuffers;
m_debug_text=s.m_debug_text; m_debug_text=s.m_debug_text;
volumetric_environment_enable=s.volumetric_environment_enable; volumetric_environment_enable=s.volumetric_environment_enable;
volumetric_environment_downsample=s.volumetric_environment_downsample; volumetric_environment_downsample=s.volumetric_environment_downsample;
volumetric_environment_max_distance=s.volumetric_environment_max_distance; volumetric_environment_max_distance=s.volumetric_environment_max_distance;
volumetric_environment_quality=s.volumetric_environment_quality; volumetric_environment_quality=s.volumetric_environment_quality;
volumetric_environment_intensity=s.volumetric_environment_intensity; volumetric_environment_intensity=s.volumetric_environment_intensity;
fog_near=s.fog_near; fog_near=s.fog_near;
fog_far=s.fog_far; fog_far=s.fog_far;
fog_density=s.fog_density; fog_density=s.fog_density;
fog_color=s.fog_color; fog_color=s.fog_color;
fog_type=s.fog_type; fog_type=s.fog_type;
dust_particle_intensity=s.dust_particle_intensity; dust_particle_intensity=s.dust_particle_intensity;
dust_particle_enable=s.dust_particle_enable; dust_particle_enable=s.dust_particle_enable;
perspective_nearz=s.perspective_nearz; perspective_nearz=s.perspective_nearz;
perspective_farz=s.perspective_farz; perspective_farz=s.perspective_farz;
debug_display = s.debug_display; debug_display = s.debug_display;
m_lodBias = s.m_lodBias; m_lodBias = s.m_lodBias;
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion; m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
max_anisotropy = s.max_anisotropy; max_anisotropy = s.max_anisotropy;
return *this; return *this;
} }
const Vector2 &KRRenderSettings::getViewportSize() { const Vector2 &KRRenderSettings::getViewportSize() {
return m_viewportSize; return m_viewportSize;
} }
void KRRenderSettings::setViewportSize(const Vector2 &size) { void KRRenderSettings::setViewportSize(const Vector2 &size) {
m_viewportSize = size; m_viewportSize = size;
} }
float KRRenderSettings::getPerspectiveNearZ() float KRRenderSettings::getPerspectiveNearZ()
{ {
return perspective_nearz; return perspective_nearz;
} }
float KRRenderSettings::getPerspectiveFarZ() float KRRenderSettings::getPerspectiveFarZ()
{ {
return perspective_farz; return perspective_farz;
} }
void KRRenderSettings::setPerspectiveNear(float v) void KRRenderSettings::setPerspectiveNear(float v)
{ {
if(perspective_nearz != v) { if(perspective_nearz != v) {
perspective_nearz = v; perspective_nearz = v;
} }
} }
void KRRenderSettings::setPerpsectiveFarZ(float v) void KRRenderSettings::setPerpsectiveFarZ(float v)
{ {
if(perspective_farz != v) { if(perspective_farz != v) {
perspective_farz = v; perspective_farz = v;
} }
} }
float KRRenderSettings::getLODBias() float KRRenderSettings::getLODBias()
{ {
return m_lodBias; return m_lodBias;
} }
void KRRenderSettings::setLODBias(float v) void KRRenderSettings::setLODBias(float v)
{ {
m_lodBias = v; m_lodBias = v;
} }
bool KRRenderSettings::getEnableRealtimeOcclusion() bool KRRenderSettings::getEnableRealtimeOcclusion()
{ {
return m_enable_realtime_occlusion; return m_enable_realtime_occlusion;
} }
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable) void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
{ {
m_enable_realtime_occlusion = enable; m_enable_realtime_occlusion = enable;
} }

View File

@@ -13,10 +13,8 @@
#include "KRResource+blend.h" #include "KRResource+blend.h"
std::vector<KRResource *> KRResource::LoadBlenderScene(KRContext &context, const std::string& path) { KRScene* KRResource::LoadBlenderScene(KRContext &context, const std::string& path) {
std::vector<KRResource *> resources;
KRScene *pScene = new KRScene(context, KRResource::GetFileBase(path)); KRScene *pScene = new KRScene(context, KRResource::GetFileBase(path));
resources.push_back(pScene);
KRDataBlock data; KRDataBlock data;
@@ -24,7 +22,7 @@ std::vector<KRResource *> KRResource::LoadBlenderScene(KRContext &context, const
//KRBlendFile blend_file = KRBlendFile(pFile); //KRBlendFile blend_file = KRBlendFile(pFile);
} }
return resources; return pScene;
} }

View File

@@ -7,9 +7,6 @@
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include <boost/tokenizer.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/variant.hpp>
#include "fbxsdk.h" #include "fbxsdk.h"

View File

@@ -1,341 +1,338 @@
// //
// KRResource_obj.cpp // KRResource_obj.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-03-22. // Created by Kearwood Gilbert on 12-03-22.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResource.h" #include "KRResource.h"
#include "KRMesh.h" #include "KRMesh.h"
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path) KRMesh* KRResource::LoadObj(KRContext &context, const std::string& path)
{ {
std::vector<KRResource *> resources; KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path)); KRMesh::mesh_info mi;
resources.push_back(new_mesh);
std::vector<std::string> material_names_t;
KRMesh::mesh_info mi;
KRDataBlock data;
std::vector<std::string> material_names_t;
char szSymbol[500][256];
KRDataBlock data;
int *pFaces = NULL;
char szSymbol[500][256];
vector<KRMesh::pack_material *> m_materials;
int *pFaces = NULL;
if(data.load(path)) {
vector<KRMesh::pack_material *> m_materials; // -----=====----- Get counts -----=====-----
if(data.load(path)) { int cVertexData = 0;
// -----=====----- Get counts -----=====-----
int cVertexData = 0; int cFaces = 1;
int cMaterialFaceStart = 1;
int cFaces = 1; char *pScan = (char *)data.getStart();
int cMaterialFaceStart = 1; char *pEnd = (char *)data.getEnd();
while(pScan < pEnd) {
char *pScan = (char *)data.getStart();
char *pEnd = (char *)data.getEnd(); // Scan through whitespace
while(pScan < pEnd) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
// Scan through whitespace }
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; if(*pScan == '#') {
} // Line is a comment line
if(*pScan == '#') { // Scan to the end of the line
// Line is a comment line while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
// Scan to the end of the line }
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { } else {
pScan++; int cSymbols = 0;
} while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
} else {
int cSymbols = 0; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++;
char *pDest = szSymbol[cSymbols++]; }
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { *pDest = '\0';
*pDest++ = *pScan++;
} // Scan through whitespace, but don't advance to next line
*pDest = '\0'; while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
// Scan through whitespace, but don't advance to next line }
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { }
pScan++;
} if(strcmp(szSymbol[0], "v") == 0) {
} // Vertex (v)
} else if(strcmp(szSymbol[0], "vt") == 0) {
if(strcmp(szSymbol[0], "v") == 0) { // Vertex Texture UV Coordinate (vt)
// Vertex (v) } else if(strcmp(szSymbol[0], "vn") == 0) {
} else if(strcmp(szSymbol[0], "vt") == 0) { // Vertex Normal (vn)
// Vertex Texture UV Coordinate (vt) } else if(strcmp(szSymbol[0], "f") == 0) {
} else if(strcmp(szSymbol[0], "vn") == 0) { // Face (f)
// Vertex Normal (vn) int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
} else if(strcmp(szSymbol[0], "f") == 0) { cVertexData += cFaceVertexes;
// Face (f) cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
cVertexData += cFaceVertexes; } else if(strcmp(szSymbol[0], "usemtl") == 0) {
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index // Use Material (usemtl)
if(cMaterialFaceStart - cFaces > 0) {
} else if(strcmp(szSymbol[0], "usemtl") == 0) { cFaces++;
// Use Material (usemtl)
if(cMaterialFaceStart - cFaces > 0) { }
cFaces++; material_names_t.push_back(std::string(szSymbol[1]));
}
}
material_names_t.push_back(std::string(szSymbol[1])); }
} }
}
} // -----=====----- Populate vertexes and faces -----=====-----
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
// -----=====----- Populate vertexes and faces -----=====----- assert(pFaces != NULL);
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1)); std::vector<Vector3> indexed_vertices;
assert(pFaces != NULL); std::vector<Vector2> indexed_uva;
std::vector<Vector3> indexed_normals;
std::vector<Vector3> indexed_vertices;
std::vector<Vector2> indexed_uva; int *pFace = pFaces;
std::vector<Vector3> indexed_normals; int *pMaterialFaces = pFace++;
*pMaterialFaces = 0;
int *pFace = pFaces;
int *pMaterialFaces = pFace++;
*pMaterialFaces = 0;
// --------
pScan = (char *)data.getStart();
// -------- while(pScan < pEnd) {
pScan = (char *)data.getStart(); // Scan through whitespace
while(pScan < pEnd) { while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++;
// Scan through whitespace }
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
pScan++; if(*pScan == '#') {
} // Line is a comment line
if(*pScan == '#') { // Scan to the end of the line
// Line is a comment line while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
pScan++;
// Scan to the end of the line }
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') { } else {
pScan++; int cSymbols = 0;
} while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
} else {
int cSymbols = 0; char *pDest = szSymbol[cSymbols++];
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') { while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
*pDest++ = *pScan++;
char *pDest = szSymbol[cSymbols++]; }
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') { *pDest = '\0';
*pDest++ = *pScan++;
} // Scan through whitespace, but don't advance to next line
*pDest = '\0'; while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
pScan++;
// Scan through whitespace, but don't advance to next line }
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) { }
pScan++;
} if(strcmp(szSymbol[0], "v") == 0) {
} // Vertex (v)
float x, y, z;
if(strcmp(szSymbol[0], "v") == 0) { char *pChar = szSymbol[1];
// Vertex (v) x = strtof(pChar, &pChar);
float x, y, z; pChar = szSymbol[2];
char *pChar = szSymbol[1]; y = strtof(pChar, &pChar);
x = strtof(pChar, &pChar); pChar = szSymbol[3];
pChar = szSymbol[2]; z = strtof(pChar, &pChar);
y = strtof(pChar, &pChar); indexed_vertices.push_back(Vector3::Create(x,y,z));
pChar = szSymbol[3]; } else if(strcmp(szSymbol[0], "vt") == 0) {
z = strtof(pChar, &pChar); // Vertex Texture UV Coordinate (vt)
indexed_vertices.push_back(Vector3::Create(x,y,z)); char *pChar = szSymbol[1];
} else if(strcmp(szSymbol[0], "vt") == 0) { float u,v;
// Vertex Texture UV Coordinate (vt)
char *pChar = szSymbol[1]; u = strtof(pChar, &pChar);
float u,v; pChar = szSymbol[2];
v = strtof(pChar, &pChar);
u = strtof(pChar, &pChar); indexed_uva.push_back(Vector2::Create(u,v));
pChar = szSymbol[2]; } else if(strcmp(szSymbol[0], "vn") == 0) {
v = strtof(pChar, &pChar); // Vertex Normal (vn)
indexed_uva.push_back(Vector2::Create(u,v)); float x,y,z;
} else if(strcmp(szSymbol[0], "vn") == 0) { char *pChar = szSymbol[1];
// Vertex Normal (vn) x = strtof(pChar, &pChar);
float x,y,z; pChar = szSymbol[2];
char *pChar = szSymbol[1]; y = strtof(pChar, &pChar);
x = strtof(pChar, &pChar); pChar = szSymbol[3];
pChar = szSymbol[2]; z = strtof(pChar, &pChar);
y = strtof(pChar, &pChar); indexed_normals.push_back(Vector3::Create(x,y,z));
pChar = szSymbol[3]; } else if(strcmp(szSymbol[0], "f") == 0) {
z = strtof(pChar, &pChar); // Face (f)
indexed_normals.push_back(Vector3::Create(x,y,z)); int cFaceVertices = cSymbols - 1;
} else if(strcmp(szSymbol[0], "f") == 0) {
// Face (f) *pFace++ = cFaceVertices;
int cFaceVertices = cSymbols - 1; for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
char *pChar = szSymbol[iSymbol];
*pFace++ = cFaceVertices; if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) { *pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
char *pChar = szSymbol[iSymbol];
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) { if(*pChar == '/') {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index pChar++;
if(*pChar == '/') {
if(*pChar == '/') { *pFace++ = -1;
pChar++; } else {
if(*pChar == '/') { *pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
*pFace++ = -1; }
} else { } else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index *pFace++ = -1;
} }
} else {
*pFace++ = -1; if(*pChar == '/') {
} pChar++;
if(*pChar == '/') {
if(*pChar == '/') { *pFace++ = -1;
pChar++; } else {
if(*pChar == '/') { *pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
*pFace++ = -1; }
} else { } else {
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index *pFace++ = -1;
} }
} else { while(*pChar == '/') {
*pFace++ = -1; pChar++;
} strtol(pChar, &pChar, 10);
while(*pChar == '/') { }
pChar++; }
strtol(pChar, &pChar, 10); }
}
}
} } else if(strcmp(szSymbol[0], "usemtl") == 0) {
// Use Material (usemtl)
if(pFace - pMaterialFaces > 1) {
} else if(strcmp(szSymbol[0], "usemtl") == 0) { *pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
// Use Material (usemtl) pMaterialFaces = pFace++;
if(pFace - pMaterialFaces > 1) { }
*pMaterialFaces = pFace - pMaterialFaces - 1; }
pMaterialFaces = pFace++; }
} }
}
}
} *pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
*pFace++ = 0;
*pMaterialFaces = pFace - pMaterialFaces - 1;
*pFace++ = 0; int iVertex = 0;
int iVertex = 0; std::vector<std::string>::iterator material_itr = material_names_t.begin();
KRMesh::pack_material *pMaterial = new KRMesh::pack_material();
pMaterial->start_vertex = iVertex;
std::vector<std::string>::iterator material_itr = material_names_t.begin(); pMaterial->vertex_count = 0;
KRMesh::pack_material *pMaterial = new KRMesh::pack_material(); memset(pMaterial->szName, 0, 256);
pMaterial->start_vertex = iVertex; if(material_itr < material_names_t.end()) {
pMaterial->vertex_count = 0; strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
memset(pMaterial->szName, 256, 0); }
if(material_itr < material_names_t.end()) { m_materials.push_back(pMaterial);
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
}
m_materials.push_back(pMaterial); pFace = pFaces;
while(*pFace != 0 && iVertex < cVertexData) {
pMaterial->start_vertex = iVertex;
pFace = pFaces;
while(*pFace != 0 && iVertex < cVertexData) { int *pMaterialEndFace = pFace + *pFace;
pMaterial->start_vertex = iVertex; ++pFace;
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
int *pMaterialEndFace = pFace + *pFace; int cFaceVertexes = *pFace;
++pFace; Vector3 firstFaceVertex;
while(pFace < pMaterialEndFace && iVertex < cVertexData) { Vector3 prevFaceVertex;
int cFaceVertexes = *pFace; Vector3 firstFaceNormal;
Vector3 firstFaceVertex; Vector3 prevFaceNormal;
Vector3 prevFaceVertex; Vector2 firstFaceUva;
Vector3 firstFaceNormal; Vector2 prevFaceUva;
Vector3 prevFaceNormal; for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
Vector2 firstFaceUva; if(iFaceVertex > 2) {
Vector2 prevFaceUva; // There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) { iVertex+=2;
if(iFaceVertex > 2) {
// There have already been 3 vertices. Now we need to split the quad into a second triangle composed of the 1st, 3rd, and 4th vertices mi.vertices.push_back(firstFaceVertex);
iVertex+=2; mi.uva.push_back(firstFaceUva);
mi.normals.push_back(firstFaceNormal);
mi.vertices.push_back(firstFaceVertex);
mi.uva.push_back(firstFaceUva); mi.vertices.push_back(prevFaceVertex);
mi.normals.push_back(firstFaceNormal); mi.uva.push_back(prevFaceUva);
mi.normals.push_back(prevFaceNormal);
mi.vertices.push_back(prevFaceVertex); }
mi.uva.push_back(prevFaceUva); Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
mi.normals.push_back(prevFaceNormal); Vector2 new_uva;
} if(pFace[iFaceVertex*3+2] >= 0) {
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]]; new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
Vector2 new_uva; }
if(pFace[iFaceVertex*3+2] >= 0) { Vector3 normal;
new_uva = indexed_uva[pFace[iFaceVertex*3+2]]; if(pFace[iFaceVertex*3+3] >= 0){
} Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]];
Vector3 normal; }
if(pFace[iFaceVertex*3+3] >= 0){
Vector3 normal = indexed_normals[pFace[iFaceVertex*3+3]]; mi.vertices.push_back(vertex);
} mi.uva.push_back(new_uva);
mi.normals.push_back(normal);
mi.vertices.push_back(vertex);
mi.uva.push_back(new_uva); if(iFaceVertex==0) {
mi.normals.push_back(normal); firstFaceVertex = vertex;
firstFaceUva = new_uva;
if(iFaceVertex==0) { firstFaceNormal = normal;
firstFaceVertex = vertex; }
firstFaceUva = new_uva; prevFaceVertex = vertex;
firstFaceNormal = normal; prevFaceUva = new_uva;
} prevFaceNormal = normal;
prevFaceVertex = vertex;
prevFaceUva = new_uva; iVertex++;
prevFaceNormal = normal; }
pFace += cFaceVertexes * 3 + 1;
iVertex++; }
} pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
pFace += cFaceVertexes * 3 + 1; if(*pFace != 0) {
} pMaterial = new KRMesh::pack_material();
pMaterial->vertex_count = iVertex - pMaterial->start_vertex; pMaterial->start_vertex = iVertex;
if(*pFace != 0) { pMaterial->vertex_count = 0;
pMaterial = new KRMesh::pack_material(); memset(pMaterial->szName, 0, 256);
pMaterial->start_vertex = iVertex;
pMaterial->vertex_count = 0; if(material_itr < material_names_t.end()) {
memset(pMaterial->szName, 256, 0); strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
}
if(material_itr < material_names_t.end()) { m_materials.push_back(pMaterial);
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256); }
} }
m_materials.push_back(pMaterial);
} for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) {
} KRMesh::pack_material *pNewMaterial = m_materials[iMaterial];
if(pNewMaterial->vertex_count > 0) {
for(int iMaterial=0; iMaterial < m_materials.size(); iMaterial++) { mi.material_names.push_back(std::string(pNewMaterial->szName));
KRMesh::pack_material *pNewMaterial = m_materials[iMaterial]; mi.submesh_starts.push_back(pNewMaterial->start_vertex);
if(pNewMaterial->vertex_count > 0) { mi.submesh_lengths.push_back(pNewMaterial->vertex_count);
mi.material_names.push_back(std::string(pNewMaterial->szName)); }
mi.submesh_starts.push_back(pNewMaterial->start_vertex); delete pNewMaterial;
mi.submesh_lengths.push_back(pNewMaterial->vertex_count); }
}
delete pNewMaterial; // TODO: Bones not yet supported for OBJ
} // std::vector<std::string> bone_names;
// std::vector<Matrix4> bone_bind_poses;
// TODO: Bones not yet supported for OBJ // std::vector<std::vector<int> > bone_indexes;
// std::vector<std::string> bone_names; // std::vector<std::vector<float> > bone_weights;
// std::vector<Matrix4> bone_bind_poses; //
// std::vector<std::vector<int> > bone_indexes; // std::vector<__uint16_t> vertex_indexes;
// std::vector<std::vector<float> > bone_weights; // std::vector<std::pair<int, int> > vertex_index_bases;
//
// std::vector<__uint16_t> vertex_indexes; mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
// std::vector<std::pair<int, int> > vertex_index_bases; new_mesh->LoadData(mi, true, false);
}
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
new_mesh->LoadData(mi, true, false); if(pFaces) {
} free(pFaces);
}
if(pFaces) {
free(pFaces); return new_mesh;
} }
return resources;
}

View File

@@ -8,6 +8,7 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResource.h" #include "KRResource.h"
#include "KRBundle.h"
KRResource::KRResource(KRContext &context, std::string name) : KRContextObject(context) { KRResource::KRResource(KRContext &context, std::string name) : KRContextObject(context) {
m_name = name; m_name = name;
@@ -33,6 +34,10 @@ std::string KRResource::GetFileExtension(const std::string& name)
std::string KRResource::GetFileBase(const std::string& name) std::string KRResource::GetFileBase(const std::string& name)
{ {
std::string f = name; std::string f = name;
// Normalize Windows Paths
std::replace(f.begin(), f.end(), '\\', '/');
// Strip off directory // Strip off directory
if(f.find_last_of("/") != std::string::npos) { if(f.find_last_of("/") != std::string::npos) {
f = f.substr(f.find_last_of("/") + 1); f = f.substr(f.find_last_of("/") + 1);
@@ -63,4 +68,15 @@ bool KRResource::save(const std::string& path)
} else { } else {
return false; return false;
} }
} }
KrResult KRResource::moveToBundle(KRBundle* bundle)
{
KRDataBlock* data = bundle->append(*this);
if (data == nullptr) {
return KR_ERROR_UNEXPECTED;
}
// TODO(kearwood) - We must re-attach the KRResource to the returned KRDataBlock
delete data;
return KR_SUCCESS;
}

View File

@@ -1,47 +1,50 @@
// //
// KRResource.h // KRResource.h
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-03-22. // Created by Kearwood Gilbert on 12-03-22.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
#ifndef KRRESOURCE_H #ifndef KRRESOURCE_H
#define KRRESOURCE_H #define KRRESOURCE_H
class KRBundle;
class KRResource : public KRContextObject class KRScene;
{ class KRMesh;
public: class KRResource : public KRContextObject
std::string getName(); {
virtual std::string getExtension() = 0; public:
virtual bool save(const std::string& path); std::string getName();
virtual bool save(KRDataBlock &data) = 0; virtual std::string getExtension() = 0;
virtual bool save(const std::string& path);
static std::string GetFileExtension(const std::string& name); virtual bool save(KRDataBlock &data) = 0;
static std::string GetFileBase(const std::string& name);
static std::string GetFilePath(const std::string& name); KrResult moveToBundle(KRBundle* bundle);
virtual ~KRResource(); static std::string GetFileExtension(const std::string& name);
static std::string GetFileBase(const std::string& name);
static std::string GetFilePath(const std::string& name);
static std::vector<KRResource *> LoadObj(KRContext &context, const std::string& path);
#if !TARGET_OS_IPHONE virtual ~KRResource();
static void LoadFbx(KRContext &context, const std::string& path);
static std::vector<KRResource *> LoadBlenderScene(KRContext &context, const std::string& path); static KRMesh* LoadObj(KRContext &context, const std::string& path);
#endif #if !TARGET_OS_IPHONE
// static KRScene* LoadFbx(KRContext &context, const std::string& path); TODO, FINDME, HACK! - Uncomment
protected: static KRScene* LoadBlenderScene(KRContext &context, const std::string& path);
KRResource(KRContext &context, std::string name); #endif
protected:
private: KRResource(KRContext &context, std::string name);
std::string m_name;
private:
}; std::string m_name;
#endif
};
#endif

View File

@@ -1,8 +1,8 @@
// //
// flare.fsh // KRResourceManager.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2019 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
@@ -29,6 +29,15 @@
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
void main() { #include "KRResourceManager.h"
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0); #include "KREngine-common.h"
KRResourceManager::KRResourceManager(KRContext &context) : KRContextObject(context)
{
}
KRResourceManager::~KRResourceManager()
{
} }

View File

@@ -1,7 +1,8 @@
// //
// sky_box.vsh // KRResourceManager.h
// KREngine // KREngine
// //
//
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
@@ -28,22 +29,22 @@
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
//
attribute vec4 vertex_position; #ifndef KRRESOURCEMANAGER_H
//attribute lowp vec4 vertex_uv; #define KRRESOURCEMANAGER_H
// #include "KREngine-common.h"
//varying mediump vec2 textureCoordinate;
varying mediump vec3 texCoord; #include "KRResource.h"
uniform highp mat4 inv_mvp_matrix_no_translate; // Inverse of the model-view-projection matrix, without view translation component #include "KRContextObject.h"
uniform mediump vec4 viewport; #include "KRDataBlock.h"
void main() class KRResourceManager : public KRContextObject {
{ public:
gl_Position = vec4(vertex_position.xy, 1.0, 1.0); KRResourceManager(KRContext &context);
virtual ~KRResourceManager();
virtual KRResource* loadResource(const std::string &name, const std::string &extension, KRDataBlock *data) = 0;
virtual KRResource* getResource(const std::string &name, const std::string &extension) = 0;
};
vec4 t = inv_mvp_matrix_no_translate * vec4(vertex_position.xy, 1.0, 1.0); #endif // KRRESOURCEMANAGER_H
t *= 1.0 / t.w;
texCoord = vec3(t);
}

View File

@@ -1,166 +1,166 @@
// //
// KRReverbZone.cpp // KRReverbZone.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-12-06. // Created by Kearwood Gilbert on 2012-12-06.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRReverbZone.h" #include "KRReverbZone.h"
#include "KRContext.h" #include "KRContext.h"
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name) KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_reverb = ""; m_reverb = "";
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
KRReverbZone::~KRReverbZone() KRReverbZone::~KRReverbZone()
{ {
} }
std::string KRReverbZone::getElementName() { std::string KRReverbZone::getElementName() {
return "reverb_zone"; return "reverb_zone";
} }
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("zone", m_zone.c_str()); e->SetAttribute("zone", m_zone.c_str());
e->SetAttribute("sample", m_reverb.c_str()); e->SetAttribute("sample", m_reverb.c_str());
e->SetAttribute("gain", m_reverb_gain); e->SetAttribute("gain", m_reverb_gain);
e->SetAttribute("gradient", m_gradient_distance); e->SetAttribute("gradient", m_gradient_distance);
return e; return e;
} }
void KRReverbZone::loadXML(tinyxml2::XMLElement *e) void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
{ {
KRNode::loadXML(e); KRNode::loadXML(e);
m_zone = e->Attribute("zone"); m_zone = e->Attribute("zone");
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
m_gradient_distance = 0.25f; m_gradient_distance = 0.25f;
} }
m_reverb = e->Attribute("sample"); m_reverb = e->Attribute("sample");
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
m_reverb_gain = 1.0f; m_reverb_gain = 1.0f;
} }
} }
std::string KRReverbZone::getReverb() std::string KRReverbZone::getReverb()
{ {
return m_reverb; return m_reverb;
} }
void KRReverbZone::setReverb(const std::string &reverb) void KRReverbZone::setReverb(const std::string &reverb)
{ {
m_reverb = reverb; m_reverb = reverb;
} }
float KRReverbZone::getReverbGain() float KRReverbZone::getReverbGain()
{ {
return m_reverb_gain; return m_reverb_gain;
} }
void KRReverbZone::setReverbGain(float reverb_gain) void KRReverbZone::setReverbGain(float reverb_gain)
{ {
m_reverb_gain = reverb_gain; m_reverb_gain = reverb_gain;
} }
std::string KRReverbZone::getZone() std::string KRReverbZone::getZone()
{ {
return m_zone; return m_zone;
} }
void KRReverbZone::setZone(const std::string &zone) void KRReverbZone::setZone(const std::string &zone)
{ {
m_zone = zone; m_zone = zone;
} }
void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) void KRReverbZone::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass)
{ {
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES; bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) { if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
Matrix4 sphereModelMatrix = getModelMatrix(); Matrix4 sphereModelMatrix = getModelMatrix();
KRShader *pShader = getContext().getShaderManager()->getShader("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("visualize_overlay", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere"); std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
if(sphereModels.size()) { if(sphereModels.size()) {
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) { for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f); sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
} }
} }
// Enable alpha blending // Enable alpha blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
} }
} }
} }
float KRReverbZone::getGradientDistance() float KRReverbZone::getGradientDistance()
{ {
return m_gradient_distance; return m_gradient_distance;
} }
void KRReverbZone::setGradientDistance(float gradient_distance) void KRReverbZone::setGradientDistance(float gradient_distance)
{ {
m_gradient_distance = gradient_distance; m_gradient_distance = gradient_distance;
} }
AABB KRReverbZone::getBounds() { AABB KRReverbZone::getBounds() {
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box // Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix()); return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
} }
float KRReverbZone::getContainment(const Vector3 &pos) float KRReverbZone::getContainment(const Vector3 &pos)
{ {
AABB bounds = getBounds(); AABB bounds = getBounds();
if(bounds.contains(pos)) { if(bounds.contains(pos)) {
Vector3 size = bounds.size(); Vector3 size = bounds.size();
Vector3 diff = pos - bounds.center(); Vector3 diff = pos - bounds.center();
diff = diff * 2.0f; diff = diff * 2.0f;
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z); diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
float d = diff.magnitude(); float d = diff.magnitude();
if(m_gradient_distance <= 0.0f) { if(m_gradient_distance <= 0.0f) {
// Avoid division by zero // Avoid division by zero
d = d > 1.0f ? 0.0f : 1.0f; d = d > 1.0f ? 0.0f : 1.0f;
} else { } else {
d = (1.0f - d) / m_gradient_distance; d = (1.0f - d) / m_gradient_distance;
d = KRCLAMP(d, 0.0f, 1.0f); d = KRCLAMP(d, 0.0f, 1.0f);
} }
return d; return d;
} else { } else {
return 0.0f; return 0.0f;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -32,7 +32,7 @@
#include "KRSceneManager.h" #include "KRSceneManager.h"
#include "KRScene.h" #include "KRScene.h"
KRSceneManager::KRSceneManager(KRContext &context) : KRContextObject(context){ KRSceneManager::KRSceneManager(KRContext &context) : KRResourceManager(context){
} }
KRSceneManager::~KRSceneManager() { KRSceneManager::~KRSceneManager() {
@@ -42,6 +42,21 @@ KRSceneManager::~KRSceneManager() {
m_scenes.empty(); m_scenes.empty();
} }
KRResource* KRSceneManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("krscene") == 0) {
return loadScene(name, data);
}
return nullptr;
}
KRResource* KRSceneManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("krscene") == 0) {
return getScene(name);
}
return nullptr;
}
KRScene *KRSceneManager::loadScene(const std::string &name, KRDataBlock *data) { KRScene *KRSceneManager::loadScene(const std::string &name, KRDataBlock *data) {
std::string lowerName = name; std::string lowerName = name;
std::transform(lowerName.begin(), lowerName.end(), std::transform(lowerName.begin(), lowerName.end(),

View File

@@ -33,17 +33,22 @@
#define KRENGINE_KRSCENEMANAGER_H #define KRENGINE_KRSCENEMANAGER_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KRDataBlock.h" #include "KRDataBlock.h"
class KRScene; class KRScene;
class KRSceneManager : public KRContextObject { class KRSceneManager : public KRResourceManager {
public: public:
KRSceneManager(KRContext &context); KRSceneManager(KRContext &context);
virtual ~KRSceneManager(); virtual ~KRSceneManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
void add(KRScene *scene); void add(KRScene *scene);
KRScene *loadScene(const std::string &name, KRDataBlock *data); KRScene *loadScene(const std::string &name, KRDataBlock *data);

661
kraken/KRShader.cpp Executable file → Normal file
View File

@@ -1,596 +1,65 @@
// //
// KRShader.cpp // KRShader.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2019 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRShader.h" #include "KRShader.h"
#include "assert.h"
#include "KRLight.h" KRShader::KRShader(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
#include "KRDirectionalLight.h" {
#include "KRSpotLight.h" m_pData = new KRDataBlock();
#include "KRPointLight.h" m_extension = extension;
}
const char *KRShader::KRENGINE_UNIFORM_NAMES[] = { KRShader::KRShader(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
"material_ambient", // KRENGINE_UNIFORM_MATERIAL_AMBIENT {
"material_diffuse", // KRENGINE_UNIFORM_MATERIAL_DIFFUSE m_pData = data;
"material_specular", // KRENGINE_UNIFORM_MATERIAL_SPECULAR m_extension = extension;
"material_reflection", // KRENGINE_UNIFORM_MATERIAL_REFLECTION }
"material_alpha", // KRENGINE_UNIFORM_MATERIAL_ALPHA
"material_shininess", // KRENGINE_UNIFORM_MATERIAL_SHININESS KRShader::~KRShader()
"light_position", // KRENGINE_UNIFORM_LIGHT_POSITION {
"light_direction_model_space", // KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE delete m_pData;
"light_direction_view_space", // KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE }
"light_color", // KRENGINE_UNIFORM_LIGHT_COLOR
"light_decay_start", // KRENGINE_UNIFORM_LIGHT_DECAY_START std::string KRShader::getExtension()
"light_cutoff", // KRENGINE_UNIFORM_LIGHT_CUTOFF {
"light_intensity", // KRENGINE_UNIFORM_LIGHT_INTENSITY return m_extension;
"flare_size", // KRENGINE_UNIFORM_FLARE_SIZE }
"view_space_model_origin", // KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN
"mvp_matrix", // KRENGINE_UNIFORM_MVP bool KRShader::save(KRDataBlock &data)
"inv_projection_matrix", // KRENGINE_UNIFORM_INVP {
"inv_mvp_matrix", // KRENGINE_UNIFORM_INVMVP data.append(*m_pData);
"inv_mvp_matrix_no_translate", // KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE return true;
"model_view_inverse_transpose_matrix", // KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE }
"model_inverse_transpose_matrix", // KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE
"model_view_matrix", // KRENGINE_UNIFORM_MODEL_VIEW KRDataBlock *KRShader::getData()
"model_matrix", // KRENGINE_UNIFORM_MODEL_MATRIX {
"projection_matrix", // KRENGINE_UNIFORM_PROJECTION_MATRIX return m_pData;
"camera_position_model_space", // KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE }
"viewport", // KRENGINE_UNIFORM_VIEWPORT
"viewport_downsample", // KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE
"diffuseTexture", // KRENGINE_UNIFORM_DIFFUSETEXTURE
"specularTexture", // KRENGINE_UNIFORM_SPECULARTEXTURE
"reflectionCubeTexture", // KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE
"reflectionTexture", // KRENGINE_UNIFORM_REFLECTIONTEXTURE
"normalTexture", // KRENGINE_UNIFORM_NORMALTEXTURE
"diffuseTexture_Scale", // KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE
"specularTexture_Scale", // KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE
"reflectionTexture_Scale", // KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE
"normalTexture_Scale", // KRENGINE_UNIFORM_NORMALTEXTURE_SCALE
"normalTexture_Scale", // KRENGINE_UNIFORM_AMBIENTTEXTURE_SCALE
"diffuseTexture_Offset", // KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET
"specularTexture_Offset", // KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET
"reflectionTexture_Offset", // KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET
"normalTexture_Offset", // KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET
"ambientTexture_Offset", // KRENGINE_UNIFORM_AMBIENTTEXTURE_OFFSET
"shadow_mvp1", // KRENGINE_UNIFORM_SHADOWMVP1
"shadow_mvp2", // KRENGINE_UNIFORM_SHADOWMVP2
"shadow_mvp3", // KRENGINE_UNIFORM_SHADOWMVP3
"shadowTexture1", // KRENGINE_UNIFORM_SHADOWTEXTURE1
"shadowTexture2", // KRENGINE_UNIFORM_SHADOWTEXTURE2
"shadowTexture3", // KRENGINE_UNIFORM_SHADOWTEXTURE3
"lightmapTexture", // KRENGINE_UNIFORM_LIGHTMAPTEXTURE
"gbuffer_frame", // KRENGINE_UNIFORM_GBUFFER_FRAME
"gbuffer_depth", // KRENGINE_UNIFORM_GBUFFER_DEPTH
"depthFrame", // KRENGINE_UNIFORM_DEPTH_FRAME
"volumetricEnvironmentFrame", // KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME
"renderFrame", // KRENGINE_UNIFORM_RENDER_FRAME
"time_absolute", // KRENGINE_UNIFORM_ABSOLUTE_TIME
"fog_near", // KRENGINE_UNIFORM_FOG_NEAR
"fog_far", // KRENGINE_UNIFORM_FOG_FAR
"fog_density", // KRENGINE_UNIFORM_FOG_DENSITY
"fog_color", // KRENGINE_UNIFORM_FOG_COLOR
"fog_scale", // KRENGINE_UNIFORM_FOG_SCALE
"fog_density_premultiplied_exponential", // KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL
"fog_density_premultiplied_squared", // KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED
"slice_depth_scale", // KRENGINE_UNIFORM_SLICE_DEPTH_SCALE
"particle_origin", // KRENGINE_UNIFORM_PARTICLE_ORIGIN
"bone_transforms", // KRENGINE_UNIFORM_BONE_TRANSFORMS
"rim_color", // KRENGINE_UNIFORM_RIM_COLOR
"rim_power", // KRENGINE_UNIFORM_RIM_POWER
"fade_color", // KRENGINE_UNIFORM_FADE_COLOR
};
KRShader::KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource) : KRContextObject(context)
{
strcpy(m_szKey, szKey);
m_iProgram = 0;
GLuint vertexShader = 0, fragShader = 0;
try {
const GLchar *vertSource[2] = {options.c_str(), vertShaderSource.c_str()};
const GLchar *fragSource[2] = {options.c_str(), fragShaderSource.c_str()};
// Create shader program.
GLDEBUG(m_iProgram = glCreateProgram());
// Create and compile vertex shader.
GLDEBUG(vertexShader = glCreateShader(GL_VERTEX_SHADER));
GLDEBUG(glShaderSource(vertexShader, 2, vertSource, NULL));
GLDEBUG(glCompileShader(vertexShader));
// Report any compile issues to stderr
GLint logLength = 0;
GLDEBUG(glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetShaderInfoLog fails
GLDEBUG(glGetShaderInfoLog(vertexShader, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to compile vertex shader: %s\nShader compile log:\n%s", szKey, log);
free(log);
}
// Create and compile vertex shader.
GLDEBUG(fragShader = glCreateShader(GL_FRAGMENT_SHADER));
GLDEBUG(glShaderSource(fragShader, 2, fragSource, NULL));
GLDEBUG(glCompileShader(fragShader));
// Report any compile issues to stderr
logLength = 0; // In case glGetShaderiv fails
GLDEBUG(glGetShaderiv(fragShader, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0) {
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetShaderInfoLog fails
GLDEBUG(glGetShaderInfoLog(fragShader, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to compile fragment shader: %s\nShader compile log:\n%s", szKey, log);
free(log);
}
// Attach vertex shader to program.
GLDEBUG(glAttachShader(m_iProgram, vertexShader));
// Attach fragment shader to program.
GLDEBUG(glAttachShader(m_iProgram, fragShader));
// Bind attribute locations.
// This needs to be done prior to linking.
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_VERTEX, "vertex_position"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_NORMAL, "vertex_normal"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TANGENT, "vertex_tangent"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TEXUVA, "vertex_uv"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_TEXUVB, "vertex_lightmap_uv"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_BONEINDEXES, "bone_indexes"));
GLDEBUG(glBindAttribLocation(m_iProgram, KRMesh::KRENGINE_ATTRIB_BONEWEIGHTS, "bone_weights"));
// Link program.
GLDEBUG(glLinkProgram(m_iProgram));
GLint link_success = GL_FALSE;
GLDEBUG(glGetProgramiv(m_iProgram, GL_LINK_STATUS, &link_success));
if(link_success != GL_TRUE) {
// Report any linking issues to stderr
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to link shader program: %s", szKey);
logLength = 0; // In case glGetProgramiv fails
GLDEBUG(glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetProgramInfoLog fails
GLDEBUG(glGetProgramInfoLog(m_iProgram, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Program link log:\n%s", log);
free(log);
}
GLDEBUG(glDeleteProgram(m_iProgram));
m_iProgram = 0;
} else {
// Get uniform locations
for(int i=0; i < KRENGINE_NUM_UNIFORMS; i++ ){
GLDEBUG(m_uniforms[i] = glGetUniformLocation(m_iProgram, KRENGINE_UNIFORM_NAMES[i]));
m_uniform_value_index[i] = -1;
}
}
} catch(...) {
if(vertexShader) {
GLDEBUG(glDeleteShader(vertexShader));
vertexShader = 0;
}
if(fragShader) {
GLDEBUG(glDeleteShader(fragShader));
fragShader = 0;
}
if(m_iProgram) {
GLDEBUG(glDeleteProgram(m_iProgram));
m_iProgram = 0;
}
}
// Release vertex and fragment shaders.
if (vertexShader) {
GLDEBUG(glDeleteShader(vertexShader));
}
if (fragShader) {
GLDEBUG(glDeleteShader(fragShader));
}
}
KRShader::~KRShader() {
if(m_iProgram) {
GLDEBUG(glDeleteProgram(m_iProgram));
if(getContext().getShaderManager()->m_active_shader == this) {
getContext().getShaderManager()->m_active_shader = NULL;
}
}
}
void KRShader::setUniform(int location, float value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_float.size();
m_uniform_value_float.push_back(value);
} else if(m_uniform_value_float[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_float[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform1f(m_uniforms[location], value));
}
}
}
void KRShader::setUniform(int location, int value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_int.size();
m_uniform_value_int.push_back(value);
} else if(m_uniform_value_int[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_int[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform1i(m_uniforms[location], value));
}
}
}
void KRShader::setUniform(int location, const Vector2 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_vector2.size();
m_uniform_value_vector2.push_back(value);
} else if(m_uniform_value_vector2[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector2[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform2f(m_uniforms[location], value.x, value.y));
}
}
}
void KRShader::setUniform(int location, const Vector3 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_vector3.size();
m_uniform_value_vector3.push_back(value);
} else if(m_uniform_value_vector3[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector3[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform3f(m_uniforms[location], value.x, value.y, value.z));
}
}
}
void KRShader::setUniform(int location, const Vector4 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_vector4.size();
m_uniform_value_vector4.push_back(value);
} else if(m_uniform_value_vector4[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_vector4[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniform4f(m_uniforms[location], value.x, value.y, value.z, value.w));
}
}
}
void KRShader::setUniform(int location, const Matrix4 &value)
{
if(m_uniforms[location] != -1) {
int value_index = m_uniform_value_index[location];
bool needs_update = true;
if(value_index == -1) {
m_uniform_value_index[location] = m_uniform_value_mat4.size();
m_uniform_value_mat4.push_back(value);
} else if(m_uniform_value_mat4[value_index] == value) {
needs_update = false;
} else {
m_uniform_value_mat4[value_index] = value;
}
if(needs_update) {
GLDEBUG(glUniformMatrix4fv(m_uniforms[location], 1, GL_FALSE, value.c));
}
}
}
bool KRShader::bind(KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color) {
if(m_iProgram == 0) {
return false;
}
bool shander_changed = false;
if(getContext().getShaderManager()->m_active_shader != this) {
getContext().getShaderManager()->m_active_shader = this;
GLDEBUG(glUseProgram(m_iProgram));
shander_changed = true;
}
setUniform(KRENGINE_UNIFORM_ABSOLUTE_TIME, getContext().getAbsoluteTime());
int light_directional_count = 0;
//int light_point_count = 0;
//int light_spot_count = 0;
// TODO - Need to support multiple lights and more light types in forward rendering
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
for(std::vector<KRDirectionalLight *>::const_iterator light_itr=directional_lights.begin(); light_itr != directional_lights.end(); light_itr++) {
KRDirectionalLight *directional_light = (*light_itr);
if(light_directional_count == 0) {
int cShadowBuffers = directional_light->getShadowBufferCount();
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE1] != -1 && cShadowBuffers > 0) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 3, directional_light->getShadowTextures()[0])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(3, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(3, GL_CLAMP_TO_EDGE);
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE2] != -1 && cShadowBuffers > 1 && camera.settings.m_cShadowBuffers > 1) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 4, directional_light->getShadowTextures()[1])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(4, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(4, GL_CLAMP_TO_EDGE);
}
if(m_uniforms[KRENGINE_UNIFORM_SHADOWTEXTURE3] != -1 && cShadowBuffers > 2 && camera.settings.m_cShadowBuffers > 2) {
if(m_pContext->getTextureManager()->selectTexture(GL_TEXTURE_2D, 5, directional_light->getShadowTextures()[2])) {
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GLDEBUG(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
}
m_pContext->getTextureManager()->_setWrapModeS(5, GL_CLAMP_TO_EDGE);
m_pContext->getTextureManager()->_setWrapModeT(5, GL_CLAMP_TO_EDGE);
}
Matrix4 matBias;
matBias.translate(1.0, 1.0, 1.0);
matBias.scale(0.5);
for(int iShadow=0; iShadow < cShadowBuffers; iShadow++) {
setUniform(KRENGINE_UNIFORM_SHADOWMVP1 + iShadow, matModel * directional_light->getShadowViewports()[iShadow].getViewProjectionMatrix() * matBias);
}
if(m_uniforms[KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE] != -1) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
// Bind the light direction vector
Vector3 lightDirObject = Matrix4::Dot(inverseModelMatrix, directional_light->getWorldLightDirection());
lightDirObject.normalize();
setUniform(KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE, lightDirObject);
}
}
light_directional_count++;
}
//light_point_count = point_lights.size();
//light_spot_count = spot_lights.size();
}
if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) {
Matrix4 inverseModelMatrix = matModel;
inverseModelMatrix.invert();
if(m_uniforms[KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE] != -1) {
// Transform location of camera to object space for calculation of specular halfVec
Vector3 cameraPosObject = Matrix4::Dot(inverseModelMatrix, viewport.getCameraPosition());
setUniform(KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE, cameraPosObject);
}
}
if(m_uniforms[KRENGINE_UNIFORM_MVP] != -1 || m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP] != -1) {
// Bind our modelmatrix variable to be a uniform called mvpmatrix in our shaderprogram
Matrix4 mvpMatrix = matModel * viewport.getViewProjectionMatrix();
setUniform(KRENGINE_UNIFORM_MVP, mvpMatrix);
if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP] != -1) {
setUniform(KRShader::KRENGINE_UNIFORM_INVMVP, Matrix4::Invert(mvpMatrix));
}
}
if(m_uniforms[KRShader::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1 || m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1 || m_uniforms[KRShader::KRENGINE_UNIFORM_MODEL_VIEW] != -1) {
Matrix4 matModelView = matModel * viewport.getViewMatrix();
setUniform(KRENGINE_UNIFORM_MODEL_VIEW, matModelView);
if(m_uniforms[KRShader::KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN] != -1) {
Vector3 view_space_model_origin = Matrix4::Dot(matModelView, Vector3::Zero()); // Origin point of model space is the light source position. No perspective, so no w divide required
setUniform(KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN, view_space_model_origin);
}
if(m_uniforms[KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE] != -1) {
Matrix4 matModelViewInverseTranspose = matModelView;
matModelViewInverseTranspose.transpose();
matModelViewInverseTranspose.invert();
setUniform(KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE, matModelViewInverseTranspose);
}
}
if(m_uniforms[KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE] != -1) {
Matrix4 matModelInverseTranspose = matModel;
matModelInverseTranspose.transpose();
matModelInverseTranspose.invert();
setUniform(KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE, matModelInverseTranspose);
}
if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVP] != -1) {
setUniform(KRENGINE_UNIFORM_INVP, viewport.getInverseProjectionMatrix());
}
if(m_uniforms[KRShader::KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE] != -1) {
Matrix4 matInvMVPNoTranslate = matModel * viewport.getViewMatrix();;
// Remove the translation
matInvMVPNoTranslate.getPointer()[3] = 0;
matInvMVPNoTranslate.getPointer()[7] = 0;
matInvMVPNoTranslate.getPointer()[11] = 0;
matInvMVPNoTranslate.getPointer()[12] = 0;
matInvMVPNoTranslate.getPointer()[13] = 0;
matInvMVPNoTranslate.getPointer()[14] = 0;
matInvMVPNoTranslate.getPointer()[15] = 1.0;
matInvMVPNoTranslate = matInvMVPNoTranslate * viewport.getProjectionMatrix();
matInvMVPNoTranslate.invert();
setUniform(KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE, matInvMVPNoTranslate);
}
setUniform(KRENGINE_UNIFORM_MODEL_MATRIX, matModel);
if(m_uniforms[KRENGINE_UNIFORM_PROJECTION_MATRIX] != -1) {
setUniform(KRENGINE_UNIFORM_PROJECTION_MATRIX, viewport.getProjectionMatrix());
}
if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT] != -1) {
setUniform(KRENGINE_UNIFORM_VIEWPORT, Vector4::Create(
(GLfloat)0.0,
(GLfloat)0.0,
(GLfloat)viewport.getSize().x,
(GLfloat)viewport.getSize().y
)
);
}
if(m_uniforms[KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE] != -1) {
setUniform(KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE, camera.getDownsample());
}
// Rim highlighting parameters
setUniform(KRENGINE_UNIFORM_RIM_COLOR, rim_color);
setUniform(KRENGINE_UNIFORM_RIM_POWER, rim_power);
// Fade parameters
setUniform(KRENGINE_UNIFORM_FADE_COLOR, fade_color);
// Fog parameters
setUniform(KRENGINE_UNIFORM_FOG_NEAR, camera.settings.fog_near);
setUniform(KRENGINE_UNIFORM_FOG_FAR, camera.settings.fog_far);
setUniform(KRENGINE_UNIFORM_FOG_DENSITY, camera.settings.fog_density);
setUniform(KRENGINE_UNIFORM_FOG_COLOR, camera.settings.fog_color);
if(m_uniforms[KRENGINE_UNIFORM_FOG_SCALE] != -1) {
setUniform(KRENGINE_UNIFORM_FOG_SCALE, 1.0f / (camera.settings.fog_far - camera.settings.fog_near));
}
if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL] != -1) {
setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL, -camera.settings.fog_density * 1.442695f); // -fog_density / log(2)
}
if(m_uniforms[KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED] != -1) {
setUniform(KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED, (float)(-camera.settings.fog_density * camera.settings.fog_density * 1.442695)); // -fog_density * fog_density / log(2)
}
// Sets the diffuseTexture variable to the first texture unit
setUniform(KRENGINE_UNIFORM_DIFFUSETEXTURE, 0);
// Sets the specularTexture variable to the second texture unit
setUniform(KRENGINE_UNIFORM_SPECULARTEXTURE, 1);
// Sets the normalTexture variable to the third texture unit
setUniform(KRENGINE_UNIFORM_NORMALTEXTURE, 2);
// Sets the shadowTexture variable to the fourth texture unit
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE1, 3);
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE2, 4);
setUniform(KRENGINE_UNIFORM_SHADOWTEXTURE3, 5);
setUniform(KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE, 4);
setUniform(KRENGINE_UNIFORM_LIGHTMAPTEXTURE, 5);
setUniform(KRENGINE_UNIFORM_GBUFFER_FRAME, 6);
setUniform(KRENGINE_UNIFORM_GBUFFER_DEPTH, 7); // Texture unit 7 is used for reading the depth buffer in gBuffer pass #2 and in post-processing pass
setUniform(KRENGINE_UNIFORM_REFLECTIONTEXTURE, 7); // Texture unit 7 is used for the reflection map textures in gBuffer pass #3 and when using forward rendering
setUniform(KRENGINE_UNIFORM_DEPTH_FRAME, 0);
setUniform(KRENGINE_UNIFORM_RENDER_FRAME, 1);
setUniform(KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME, 2);
#if defined(DEBUG)
if(shander_changed) { // FINDME!! KIP!! HACK!!
GLint logLength;
GLint validate_status = GL_FALSE;
GLDEBUG(glValidateProgram(m_iProgram));
GLDEBUG(glGetProgramiv(m_iProgram, GL_VALIDATE_STATUS, &validate_status));
if(validate_status != GL_TRUE) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KREngine - Failed to validate shader program: %s", m_szKey);
logLength = 0; // In case glGetProgramiv fails
GLDEBUG(glGetProgramiv(m_iProgram, GL_INFO_LOG_LENGTH, &logLength));
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength + 1);
assert(log != NULL);
log[0] = '\0'; // In case glGetProgramInfoLog fails
GLDEBUG(glGetProgramInfoLog(m_iProgram, logLength, &logLength, log));
log[logLength] = '\0';
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Program validate log:\n%s", log);
free(log);
}
return false;
}
}
#endif
return true;
}
const char *KRShader::getKey() const {
return m_szKey;
}

144
kraken/KRShader.h Executable file → Normal file
View File

@@ -2,18 +2,18 @@
// KRShader.h // KRShader.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2019 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
@@ -23,139 +23,37 @@
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#ifndef KRSHADER_H #ifndef KRSHADER_H
#define KRSHADER_H #define KRSHADER_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRShader.h" #include "KRContextObject.h"
#include "KRCamera.h" #include "KRDataBlock.h"
#include "KRNode.h" #include "KRResource.h"
#include "KRViewport.h"
class KRShader : public KRContextObject { class KRShader : public KRResource {
public: public:
KRShader(KRContext &context, char *szKey, std::string options, std::string vertShaderSource, const std::string fragShaderSource); KRShader(KRContext &context, std::string name, std::string extension);
KRShader(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
virtual ~KRShader(); virtual ~KRShader();
const char *getKey() const;
bool bind(KRCamera &camera, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color); virtual std::string getExtension();
enum { virtual bool save(KRDataBlock &data);
KRENGINE_UNIFORM_MATERIAL_AMBIENT = 0,
KRENGINE_UNIFORM_MATERIAL_DIFFUSE,
KRENGINE_UNIFORM_MATERIAL_SPECULAR,
KRENGINE_UNIFORM_MATERIAL_REFLECTION,
KRENGINE_UNIFORM_MATERIAL_ALPHA,
KRENGINE_UNIFORM_MATERIAL_SHININESS,
KRENGINE_UNIFORM_LIGHT_POSITION,
KRENGINE_UNIFORM_LIGHT_DIRECTION_MODEL_SPACE,
KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE,
KRENGINE_UNIFORM_LIGHT_COLOR,
KRENGINE_UNIFORM_LIGHT_DECAY_START,
KRENGINE_UNIFORM_LIGHT_CUTOFF,
KRENGINE_UNIFORM_LIGHT_INTENSITY,
KRENGINE_UNIFORM_FLARE_SIZE,
KRENGINE_UNIFORM_VIEW_SPACE_MODEL_ORIGIN,
KRENGINE_UNIFORM_MVP,
KRENGINE_UNIFORM_INVP,
KRENGINE_UNIFORM_INVMVP,
KRENGINE_UNIFORM_INVMVP_NO_TRANSLATE,
KRENGINE_UNIFORM_MODEL_VIEW_INVERSE_TRANSPOSE,
KRENGINE_UNIFORM_MODEL_INVERSE_TRANSPOSE,
KRENGINE_UNIFORM_MODEL_VIEW,
KRENGINE_UNIFORM_MODEL_MATRIX,
KRENGINE_UNIFORM_PROJECTION_MATRIX,
KRENGINE_UNIFORM_CAMERAPOS_MODEL_SPACE,
KRENGINE_UNIFORM_VIEWPORT,
KRENGINE_UNIFORM_VIEWPORT_DOWNSAMPLE,
KRENGINE_UNIFORM_DIFFUSETEXTURE,
KRENGINE_UNIFORM_SPECULARTEXTURE,
KRENGINE_UNIFORM_REFLECTIONCUBETEXTURE,
KRENGINE_UNIFORM_REFLECTIONTEXTURE,
KRENGINE_UNIFORM_NORMALTEXTURE,
KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE,
KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE,
KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE,
KRENGINE_UNIFORM_NORMALTEXTURE_SCALE,
KRENGINE_UNIFORM_AMBIENTTEXTURE_SCALE,
KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET,
KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET,
KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET,
KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET,
KRENGINE_UNIFORM_AMBIENTTEXTURE_OFFSET,
KRENGINE_UNIFORM_SHADOWMVP1,
KRENGINE_UNIFORM_SHADOWMVP2,
KRENGINE_UNIFORM_SHADOWMVP3,
KRENGINE_UNIFORM_SHADOWTEXTURE1,
KRENGINE_UNIFORM_SHADOWTEXTURE2,
KRENGINE_UNIFORM_SHADOWTEXTURE3,
KRENGINE_UNIFORM_LIGHTMAPTEXTURE,
KRENGINE_UNIFORM_GBUFFER_FRAME,
KRENGINE_UNIFORM_GBUFFER_DEPTH,
KRENGINE_UNIFORM_DEPTH_FRAME,
KRENGINE_UNIFORM_VOLUMETRIC_ENVIRONMENT_FRAME,
KRENGINE_UNIFORM_RENDER_FRAME,
KRENGINE_UNIFORM_ABSOLUTE_TIME,
KRENGINE_UNIFORM_FOG_NEAR,
KRENGINE_UNIFORM_FOG_FAR,
KRENGINE_UNIFORM_FOG_DENSITY,
KRENGINE_UNIFORM_FOG_COLOR,
KRENGINE_UNIFORM_FOG_SCALE,
KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_EXPONENTIAL,
KRENGINE_UNIFORM_DENSITY_PREMULTIPLIED_SQUARED,
KRENGINE_UNIFORM_SLICE_DEPTH_SCALE,
KRENGINE_UNIFORM_PARTICLE_ORIGIN,
KRENGINE_UNIFORM_BONE_TRANSFORMS,
KRENGINE_UNIFORM_RIM_COLOR,
KRENGINE_UNIFORM_RIM_POWER,
KRENGINE_UNIFORM_FADE_COLOR,
KRENGINE_NUM_UNIFORMS
};
/*
typedef enum {
KRENGINE_UNIFORM_TYPE_UNKNOWN,
KRENGINE_UNIFORM_TYPE_FLOAT,
KRENGINE_UNIFORM_TYPE_INT,
KRENGINE_UNIFORM_TYPE_VECTOR2,
KRENGINE_UNIFORM_TYPE_VECTOR3,
KRENGINE_UNIFORM_TYPE_VECTOR4,
KRENGINE_UNIFORM_TYPE_MAT4
} uniform_type_t;
uniform_type_t m_uniform_type[KRENGINE_NUM_UNIFORMS];
*/
static const char *KRENGINE_UNIFORM_NAMES[];
GLint m_uniforms[KRENGINE_NUM_UNIFORMS];
int m_uniform_value_index[KRENGINE_NUM_UNIFORMS];
std::vector<float> m_uniform_value_float;
std::vector<int> m_uniform_value_int;
std::vector<Vector2> m_uniform_value_vector2;
std::vector<Vector3> m_uniform_value_vector3;
std::vector<Vector4> m_uniform_value_vector4;
std::vector<Matrix4> m_uniform_value_mat4;
char m_szKey[256];
void setUniform(int location, float value);
void setUniform(int location, int value);
void setUniform(int location, const Vector2 &value);
void setUniform(int location, const Vector3 &value);
void setUniform(int location, const Vector4 &value);
void setUniform(int location, const Matrix4 &value);
KRDataBlock *getData();
private: private:
GLuint m_iProgram;
std::string m_extension;
KRDataBlock *m_pData;
}; };
#endif #endif /* defined(KRSHADER_H) */

320
kraken/KRShaderManager.cpp Executable file → Normal file
View File

@@ -1,19 +1,19 @@
// //
// KRShaderManager.cpp // ShaderManager.cpp
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2019 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
@@ -23,261 +23,95 @@
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#include "KRShaderManager.h"
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRShaderManager.h" KRShaderManager::KRShaderManager(KRContext &context) : KRResourceManager(context)
#include "KRLight.h"
#include "KRDirectionalLight.h"
#include "KRSpotLight.h"
#include "KRPointLight.h"
using namespace std;
KRShaderManager::KRShaderManager(KRContext &context) : KRContextObject(context) {
m_active_shader = NULL;
}
KRShaderManager::~KRShaderManager() {
}
KRShader *KRShaderManager::getShader(const std::string &shader_name, KRCamera *pCamera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor) {
int iShadowQuality = 0; // FINDME - HACK - Placeholder code, need to iterate through lights and dynamically build shader
int light_directional_count = 0;
int light_point_count = 0;
int light_spot_count = 0;
if(renderPass != KRNode::RENDER_PASS_DEFERRED_LIGHTS && renderPass != KRNode::RENDER_PASS_DEFERRED_GBUFFER && renderPass != KRNode::RENDER_PASS_DEFERRED_OPAQUE && renderPass != KRNode::RENDER_PASS_GENERATE_SHADOWMAPS) {
light_directional_count = directional_lights.size();
light_point_count = point_lights.size();
light_spot_count = spot_lights.size();
for(std::vector<KRDirectionalLight *>::const_iterator light_itr=directional_lights.begin(); light_itr != directional_lights.end(); light_itr++) {
KRDirectionalLight *directional_light =(*light_itr);
iShadowQuality = directional_light->getShadowBufferCount();
}
}
if(iShadowQuality > pCamera->settings.m_cShadowBuffers) {
iShadowQuality = pCamera->settings.m_cShadowBuffers;
}
bool bFadeColorEnabled = pCamera->getFadeColor().w >= 0.0f;
std::pair<std::string, std::vector<int> > key;
key.first = shader_name;
key.second.push_back(light_directional_count);
key.second.push_back(light_point_count);
key.second.push_back(light_spot_count);
key.second.push_back(pCamera->settings.fog_type);
key.second.push_back(pCamera->settings.bEnablePerPixel);
key.second.push_back(bAlphaTest);
key.second.push_back(bAlphaBlend);
key.second.push_back(bDiffuseMap);
key.second.push_back(bNormalMap);
key.second.push_back(bSpecMap);
key.second.push_back(bReflectionMap);
key.second.push_back(bone_count);
key.second.push_back(bSpecMap);
key.second.push_back(bReflectionMap);
key.second.push_back(bReflectionCubeMap);
key.second.push_back(pCamera->settings.bDebugPSSM);
key.second.push_back(iShadowQuality);
key.second.push_back(pCamera->settings.bEnableAmbient);
key.second.push_back(pCamera->settings.bEnableDiffuse);
key.second.push_back(pCamera->settings.bEnableSpecular);
key.second.push_back(bLightMap);
key.second.push_back(bDiffuseMapScale);
key.second.push_back(bSpecMapScale);
key.second.push_back(bReflectionMapScale);
key.second.push_back(bNormalMapScale);
key.second.push_back(bDiffuseMapOffset);
key.second.push_back(bSpecMapOffset);
key.second.push_back(bReflectionMapOffset);
key.second.push_back(bNormalMapOffset);
key.second.push_back(pCamera->settings.volumetric_environment_enable);
key.second.push_back(pCamera->settings.volumetric_environment_downsample != 0);
key.second.push_back(renderPass);
key.second.push_back(pCamera->settings.dof_quality);
key.second.push_back(pCamera->settings.bEnableFlash);
key.second.push_back(pCamera->settings.bEnableVignette);
key.second.push_back(pCamera->settings.dof_depth * 1000.0f);
key.second.push_back(pCamera->settings.dof_falloff * 1000.0f);
key.second.push_back(pCamera->settings.flash_depth * 1000.0f);
key.second.push_back(pCamera->settings.flash_falloff * 1000.0f);
key.second.push_back(pCamera->settings.flash_intensity * 1000.0f);
key.second.push_back(pCamera->settings.vignette_radius * 1000.0f);
key.second.push_back(pCamera->settings.vignette_falloff * 1000.0f);
key.second.push_back(bRimColor);
key.second.push_back(bFadeColorEnabled);
KRShader *pShader = m_shaders[key];
if(pShader == NULL) {
if(m_shaders.size() > KRContext::KRENGINE_MAX_SHADER_HANDLES) {
// Keep the size of the shader cache reasonable
std::map<std::pair<std::string, std::vector<int> > , KRShader *>::iterator itr = m_shaders.begin();
delete (*itr).second;
m_shaders.erase(itr);
KRContext::Log(KRContext::LOG_LEVEL_INFORMATION, "Swapping shaders...\n");
}
std::string platform_shader_name = shader_name;
#if TARGET_OS_IPHONE
platform_shader_name = shader_name;
#else
platform_shader_name = shader_name + "_osx";
#endif
stringstream stream;
stream.precision(std::numeric_limits<long double>::digits10);
#if TARGET_OS_IPHONE
#else
stream << "\n#version 150";
stream << "\n#define lowp";
stream << "\n#define mediump";
stream << "\n#define highp";
#endif
stream << "\n#define LIGHT_DIRECTIONAL_COUNT " << light_directional_count;
stream << "\n#define LIGHT_POINT_COUNT " << light_point_count;
stream << "\n#define LIGHT_SPOT_COUNT " << light_spot_count;
stream << "\n#define BONE_COUNT " << bone_count;
stream << "\n#define HAS_DIFFUSE_MAP " << (bDiffuseMap ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_SCALE " << (bDiffuseMapScale ? "1" : "0");
stream << "\n#define HAS_DIFFUSE_MAP_OFFSET " << (bDiffuseMapOffset ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP " << (bSpecMap ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_SCALE " << (bSpecMapScale ? "1" : "0");
stream << "\n#define HAS_SPEC_MAP_OFFSET " << (bSpecMapOffset ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP " << (bNormalMap ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_SCALE " << (bNormalMapScale ? "1" : "0");
stream << "\n#define HAS_NORMAL_MAP_OFFSET " << (bNormalMapOffset ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP " << (bReflectionMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_SCALE " << (bReflectionMapScale ? "1" : "0");
stream << "\n#define HAS_REFLECTION_MAP_OFFSET " << (bReflectionMapOffset ? "1" : "0");
stream << "\n#define HAS_LIGHT_MAP " << (bLightMap ? "1" : "0");
stream << "\n#define HAS_REFLECTION_CUBE_MAP " << (bReflectionCubeMap ? "1" : "0");
stream << "\n#define ALPHA_TEST " << (bAlphaTest ? "1" : "0");
stream << "\n#define ALPHA_BLEND " << (bAlphaBlend ? "1" : "0");
stream << "\n#define ENABLE_PER_PIXEL " << (pCamera->settings.bEnablePerPixel ? "1" : "0");
stream << "\n#define DEBUG_PSSM " << (pCamera->settings.bDebugPSSM ? "1" : "0");
stream << "\n#define SHADOW_QUALITY " << iShadowQuality;
stream << "\n#define ENABLE_AMBIENT " << (pCamera->settings.bEnableAmbient ? "1" : "0");
stream << "\n#define ENABLE_DIFFUSE " << (pCamera->settings.bEnableDiffuse ? "1" : "0");
stream << "\n#define ENABLE_SPECULAR " << (pCamera->settings.bEnableSpecular ? "1" : "0");
stream << "\n#define ENABLE_RIM_COLOR " << (bRimColor ? "1" : "0");
stream << "\n#define ENABLE_FADE_COLOR " << (bFadeColorEnabled ? "1" : "0");
stream << "\n#define FOG_TYPE " << pCamera->settings.fog_type;
switch(renderPass) {
case KRNode::RENDER_PASS_DEFERRED_GBUFFER:
stream << "\n#define GBUFFER_PASS " << 1;
break;
case KRNode::RENDER_PASS_DEFERRED_LIGHTS:
stream << "\n#define GBUFFER_PASS " << 2;
break;
case KRNode::RENDER_PASS_DEFERRED_OPAQUE:
stream << "\n#define GBUFFER_PASS " << 3;
break;
default:
stream << "\n#define GBUFFER_PASS " << 0;
break;
}
stream << "\n#define DOF_QUALITY " << pCamera->settings.dof_quality;
stream << "\n#define ENABLE_FLASH " << (pCamera->settings.bEnableFlash ? "1" : "0");
stream << "\n#define ENABLE_VIGNETTE " << (pCamera->settings.bEnableVignette ? "1" : "0");
stream << "\n#define VOLUMETRIC_ENVIRONMENT_DOWNSAMPLED " << (pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0 ? "1" : "0");
stream.setf(ios::fixed,ios::floatfield);
stream.precision(std::numeric_limits<long double>::digits10);
stream << "\n#define DOF_DEPTH " << pCamera->settings.dof_depth;
stream << "\n#define DOF_FALLOFF " << pCamera->settings.dof_falloff;
stream << "\n#define FLASH_DEPTH " << pCamera->settings.flash_depth;
stream << "\n#define FLASH_FALLOFF " << pCamera->settings.flash_falloff;
stream << "\n#define FLASH_INTENSITY " << pCamera->settings.flash_intensity;
stream << "\n#define VIGNETTE_RADIUS " << pCamera->settings.vignette_radius;
stream << "\n#define VIGNETTE_FALLOFF " << pCamera->settings.vignette_falloff;
stream << "\n";
std::string options = stream.str();
std::string vertShaderSource = m_vertShaderSource[platform_shader_name];
std::string fragShaderSource = m_fragShaderSource[platform_shader_name];
if(vertShaderSource.length() == 0) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Vertex Shader Missing: %s", platform_shader_name.c_str());
}
if(fragShaderSource.length() == 0) {
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "Fragment Shader Missing: %s", platform_shader_name.c_str());
}
Vector4 fade_color = pCamera->getFadeColor();
char szKey[256];
sprintf(szKey, "%i_%i_%i_%i_%i_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%d_%i_%s_%i_%d_%d_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f_%f", light_directional_count, light_point_count, light_spot_count, bone_count, pCamera->settings.fog_type, pCamera->settings.bEnablePerPixel,bAlphaTest, bAlphaBlend, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, pCamera->settings.bDebugPSSM, iShadowQuality, pCamera->settings.bEnableAmbient, pCamera->settings.bEnableDiffuse, pCamera->settings.bEnableSpecular, bLightMap, bDiffuseMapScale, bSpecMapScale, bReflectionMapScale, bNormalMapScale, bDiffuseMapOffset, bSpecMapOffset, bReflectionMapOffset, bNormalMapOffset,pCamera->settings.volumetric_environment_enable && pCamera->settings.volumetric_environment_downsample != 0, renderPass, shader_name.c_str(),pCamera->settings.dof_quality,pCamera->settings.bEnableFlash,pCamera->settings.bEnableVignette,pCamera->settings.dof_depth,pCamera->settings.dof_falloff,pCamera->settings.flash_depth,pCamera->settings.flash_falloff,pCamera->settings.flash_intensity,pCamera->settings.vignette_radius,pCamera->settings.vignette_falloff, fade_color.x, fade_color.y, fade_color.z, fade_color.w);
pShader = new KRShader(getContext(), szKey, options, vertShaderSource, fragShaderSource);
m_shaders[key] = pShader;
}
return pShader;
}
bool KRShaderManager::selectShader(const std::string &shader_name, KRCamera &camera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRViewport &viewport, const Matrix4 &matModel, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color)
{ {
KRShader *pShader = getShader(shader_name, &camera, point_lights, directional_lights, spot_lights, bone_count, bDiffuseMap, bNormalMap, bSpecMap, bReflectionMap, bReflectionCubeMap, bLightMap, bDiffuseMapScale, bSpecMapScale, bNormalMapScale, bReflectionMapScale, bDiffuseMapOffset, bSpecMapOffset, bNormalMapOffset, bReflectionMapOffset, bAlphaTest, bAlphaBlend, renderPass, rim_power != 0.0f);
return selectShader(camera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, bone_count, renderPass, rim_color, rim_power, fade_color);
} }
bool KRShaderManager::selectShader(KRCamera &camera, KRShader *pShader, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color) KRShaderManager::~KRShaderManager()
{ {
if(pShader) { for(unordered_map<std::string, unordered_map<std::string, KRShader *> >::iterator extension_itr = m_shaders.begin(); extension_itr != m_shaders.end(); extension_itr++) {
return pShader->bind(camera, viewport, matModel, point_lights, directional_lights, spot_lights, renderPass, rim_color, rim_power, fade_color); for(unordered_map<std::string, KRShader *>::iterator name_itr=(*extension_itr).second.begin(); name_itr != (*extension_itr).second.end(); name_itr++) {
delete (*name_itr).second;
}
}
}
KRResource* KRShaderManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("spv") == 0) {
return load(name, extension, data);
}
return nullptr;
}
KRResource* KRShaderManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("spv") == 0) {
return get(name, extension);
}
return nullptr;
}
unordered_map<std::string, unordered_map<std::string, KRShader *> > &KRShaderManager::getShaders()
{
return m_shaders;
}
void KRShaderManager::add(KRShader *shader)
{
std::string lower_name = shader->getName();
std::string lower_extension = shader->getExtension();
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
unordered_map<std::string, unordered_map<std::string, KRShader *> >::iterator extension_itr = m_shaders.find(lower_extension);
if(extension_itr == m_shaders.end()) {
m_shaders[lower_extension] = unordered_map<std::string, KRShader *>();
extension_itr = m_shaders.find(lower_extension);
}
unordered_map<std::string, KRShader *>::iterator name_itr = (*extension_itr).second.find(lower_name);
if(name_itr != (*extension_itr).second.end()) {
delete (*name_itr).second;
(*name_itr).second = shader;
} else { } else {
return false; (*extension_itr).second[lower_name] = shader;
} }
} }
void KRShaderManager::loadFragmentShader(const std::string &name, KRDataBlock *data) { KRShader *KRShaderManager::load(const std::string &name, const std::string &extension, KRDataBlock *data)
m_fragShaderSource[name] = data->getString(); {
delete data; KRShader *shader = new KRShader(getContext(), name, extension, data);
if(shader) add(shader);
return shader;
} }
void KRShaderManager::loadVertexShader(const std::string &name, KRDataBlock *data) { KRShader *KRShaderManager::get(const std::string &name, const std::string &extension)
m_vertShaderSource[name] = data->getString(); {
delete data; std::string lower_name = name;
std::string lower_extension = extension;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_shaders[lower_extension][lower_name];
} }
const std::string &KRShaderManager::getFragShaderSource(const std::string &name) {
return m_fragShaderSource[name]; const unordered_map<std::string, KRShader *> &KRShaderManager::get(const std::string &extension)
{
std::string lower_extension = extension;
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_shaders[lower_extension];
} }
const std::string &KRShaderManager::getVertShaderSource(const std::string &name) {
return m_vertShaderSource[name];
}
long KRShaderManager::getShaderHandlesUsed() {
return m_shaders.size();
}

70
kraken/KRShaderManager.h Executable file → Normal file
View File

@@ -1,19 +1,19 @@
// //
// KRShaderManager.h // ShaderManager.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2019 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
@@ -23,57 +23,43 @@
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#ifndef KRSHADER_MANAGER_H
#define KRSHADER_MANAGER_H
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRCamera.h" #include "KRResourceManager.h"
#include "KRDataBlock.h"
#include "KRNode.h"
using std::map;
using std::vector;
#include "KRShader.h" #include "KRShader.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
#ifndef KRSHADERMANAGER_H class KRShaderManager : public KRResourceManager {
#define KRSHADERMANAGER_H
class KRShader;
class KRCamera;
class KRShaderManager : public KRContextObject {
public: public:
KRShaderManager(KRContext &context); KRShaderManager(KRContext &context);
virtual ~KRShaderManager(); virtual ~KRShaderManager();
void loadFragmentShader(const std::string &name, KRDataBlock *data);
void loadVertexShader(const std::string &name, KRDataBlock *data);
const std::string &getFragShaderSource(const std::string &name);
const std::string &getVertShaderSource(const std::string &name);
KRShader *getShader(const std::string &shader_name, KRCamera *pCamera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, bool bRimColor = false);
bool selectShader(KRCamera &camera, KRShader *pShader, const KRViewport &viewport, const Matrix4 &matModel, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRNode::RenderPass &renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color);
bool selectShader(const std::string &shader_name, KRCamera &camera, const std::vector<KRPointLight *> &point_lights, const std::vector<KRDirectionalLight *> &directional_lights, const std::vector<KRSpotLight *>&spot_lights, int bone_count, const KRViewport &viewport, const Matrix4 &matModel, bool bDiffuseMap, bool bNormalMap, bool bSpecMap, bool bReflectionMap, bool bReflectionCubeMap, bool bLightMap, bool bDiffuseMapScale,bool bSpecMapScale, bool bNormalMapScale, bool bReflectionMapScale, bool bDiffuseMapOffset, bool bSpecMapOffset, bool bNormalMapOffset, bool bReflectionMapOffset, bool bAlphaTest, bool bAlphaBlend, KRNode::RenderPass renderPass, const Vector3 &rim_color, float rim_power, const Vector4 &fade_color);
long getShaderHandlesUsed();
KRShader *m_active_shader;
private: virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
//unordered_map<std::string, KRShader *> m_shaders; virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
std::map<std::pair<std::string, std::vector<int> >, KRShader *> m_shaders;
unordered_map<std::string, std::string> m_fragShaderSource; void add(KRShader *shader);
unordered_map<std::string, std::string> m_vertShaderSource;
KRShader *load(const std::string &name, const std::string &extension, KRDataBlock *data);
KRShader *get(const std::string &name, const std::string &extension);
const unordered_map<std::string, KRShader *> &get(const std::string &extension);
unordered_map<std::string, unordered_map<std::string, KRShader *> > &getShaders();
private:
unordered_map<std::string, unordered_map<std::string, KRShader *> > m_shaders;
}; };
#endif #endif /* defined(KRUNKNOWN_MANAGER_H) */

65
kraken/KRSource.cpp Normal file
View File

@@ -0,0 +1,65 @@
//
// KRSource.cpp
// KREngine
//
// Copyright 2012 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRSource.h"
KRSource::KRSource(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
{
m_pData = new KRDataBlock();
m_extension = extension;
}
KRSource::KRSource(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
{
m_pData = data;
m_extension = extension;
}
KRSource::~KRSource()
{
delete m_pData;
}
std::string KRSource::getExtension()
{
return m_extension;
}
bool KRSource::save(KRDataBlock &data)
{
data.append(*m_pData);
return true;
}
KRDataBlock *KRSource::getData()
{
return m_pData;
}

View File

@@ -1,43 +1,59 @@
// //
// dust_particle.fsh // KRSource.h
// KREngine // KREngine
// //
// Copyright 2012 Kearwood Gilbert. All rights reserved. // Copyright 2012 Kearwood Gilbert. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without modification, are // Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met: // permitted provided that the following conditions are met:
// //
// 1. Redistributions of source code must retain the above copyright notice, this list of // 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer. // conditions and the following disclaimer.
// //
// 2. Redistributions in binary form must reproduce the above copyright notice, this list // 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 // of conditions and the following disclaimer in the documentation and/or other materials
// provided with the distribution. // provided with the distribution.
// //
// THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED // THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR // FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 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 // 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 // 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 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// The views and conclusions contained in the software and documentation are those of the // The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed // authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert. // or implied, of Kearwood Gilbert.
// //
#extension GL_EXT_shadow_samplers : require #ifndef KRSOURCE_H
#define KRSOURCE_H
varying mediump vec2 texCoord;
#include "KREngine-common.h"
varying mediump vec4 shadowMapCoord1; #include "KRContextObject.h"
uniform sampler2DShadow shadowTexture1; #include "KRDataBlock.h"
uniform mediump vec3 light_color; #include "KRResource.h"
varying lowp float intensity_modulate;
class KRSource : public KRResource {
void main() {
gl_FragColor = vec4(light_color, 1.0) * shadow2DProjEXT(shadowTexture1, shadowMapCoord1) * max(1.0 - texCoord.x*texCoord.x-texCoord.y*texCoord.y, 0.0) * intensity_modulate; public:
} KRSource(KRContext &context, std::string name, std::string extension);
KRSource(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
virtual ~KRSource();
virtual std::string getExtension();
virtual bool save(KRDataBlock &data);
KRDataBlock *getData();
private:
std::string m_extension;
KRDataBlock *m_pData;
};
#endif /* defined(KRSOURCE_H) */

148
kraken/KRSourceManager.cpp Normal file
View File

@@ -0,0 +1,148 @@
//
// SourceManager.cpp
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#include "KRSourceManager.h"
#include "KREngine-common.h"
KRSourceManager::KRSourceManager(KRContext &context) : KRResourceManager(context)
{
}
KRSourceManager::~KRSourceManager()
{
for(unordered_map<std::string, unordered_map<std::string, KRSource *> >::iterator extension_itr = m_sources.begin(); extension_itr != m_sources.end(); extension_itr++) {
for(unordered_map<std::string, KRSource *>::iterator name_itr=(*extension_itr).second.begin(); name_itr != (*extension_itr).second.end(); name_itr++) {
delete (*name_itr).second;
}
}
}
unordered_map<std::string, unordered_map<std::string, KRSource *> > &KRSourceManager::getSources()
{
return m_sources;
}
void KRSourceManager::add(KRSource *source)
{
std::string lower_name = source->getName();
std::string lower_extension = source->getExtension();
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
unordered_map<std::string, unordered_map<std::string, KRSource *> >::iterator extension_itr = m_sources.find(lower_extension);
if(extension_itr == m_sources.end()) {
m_sources[lower_extension] = unordered_map<std::string, KRSource *>();
extension_itr = m_sources.find(lower_extension);
}
unordered_map<std::string, KRSource *>::iterator name_itr = (*extension_itr).second.find(lower_name);
if(name_itr != (*extension_itr).second.end()) {
delete (*name_itr).second;
(*name_itr).second = source;
} else {
(*extension_itr).second[lower_name] = source;
}
}
KRResource* KRSourceManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
if (extension.compare("vert") == 0 ||
extension.compare("frag") == 0 ||
extension.compare("tesc") == 0 ||
extension.compare("tese") == 0 ||
extension.compare("geom") == 0 ||
extension.compare("comp") == 0 ||
extension.compare("mesh") == 0 ||
extension.compare("task") == 0 ||
extension.compare("rgen") == 0 ||
extension.compare("rint") == 0 ||
extension.compare("rahit") == 0 ||
extension.compare("rchit") == 0 ||
extension.compare("rmiss") == 0 ||
extension.compare("rcall") == 0 ||
extension.compare("glsl") == 0 ||
extension.compare("options") == 0) {
return load(name, extension, data);
}
return nullptr;
}
KRResource* KRSourceManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("vert") == 0 ||
extension.compare("frag") == 0 ||
extension.compare("tesc") == 0 ||
extension.compare("tese") == 0 ||
extension.compare("geom") == 0 ||
extension.compare("comp") == 0 ||
extension.compare("mesh") == 0 ||
extension.compare("task") == 0 ||
extension.compare("rgen") == 0 ||
extension.compare("rint") == 0 ||
extension.compare("rahit") == 0 ||
extension.compare("rchit") == 0 ||
extension.compare("rmiss") == 0 ||
extension.compare("rcall") == 0 ||
extension.compare("glsl") == 0 ||
extension.compare("options") == 0) {
return get(name, extension);
}
return nullptr;
}
KRSource *KRSourceManager::load(const std::string &name, const std::string &extension, KRDataBlock *data)
{
KRSource *source = new KRSource(getContext(), name, extension, data);
if(source) add(source);
return source;
}
KRSource *KRSourceManager::get(const std::string &name, const std::string &extension)
{
std::string lower_name = name;
std::string lower_extension = extension;
std::transform(lower_name.begin(), lower_name.end(), lower_name.begin(), ::tolower);
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_sources[lower_extension][lower_name];
}
const unordered_map<std::string, KRSource *> &KRSourceManager::get(const std::string &extension)
{
std::string lower_extension = extension;
std::transform(lower_extension.begin(), lower_extension.end(), lower_extension.begin(), ::tolower);
return m_sources[lower_extension];
}

63
kraken/KRSourceManager.h Normal file
View File

@@ -0,0 +1,63 @@
//
// SourceManager.h
// KREngine
//
// Copyright 2019 Kearwood Gilbert. 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 KEARWOOD GILBERT ''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 KEARWOOD GILBERT 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.
//
// The views and conclusions contained in the software and documentation are those of the
// authors and should not be interpreted as representing official policies, either expressed
// or implied, of Kearwood Gilbert.
//
#ifndef KRSOURCE_MANAGER_H
#define KRSOURCE_MANAGER_H
#include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRSource.h"
#include "KRContextObject.h"
#include "KRDataBlock.h"
class KRSourceManager : public KRResourceManager {
public:
KRSourceManager(KRContext &context);
virtual ~KRSourceManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
void add(KRSource *source);
KRSource *load(const std::string &name, const std::string &extension, KRDataBlock *data);
KRSource *get(const std::string &name, const std::string &extension);
const unordered_map<std::string, KRSource *> &get(const std::string &extension);
unordered_map<std::string, unordered_map<std::string, KRSource *> > &getSources();
private:
unordered_map<std::string, unordered_map<std::string, KRSource *> > m_sources;
};
#endif /* defined(KRUNKNOWN_MANAGER_H) */

View File

@@ -1,61 +1,61 @@
// //
// KRSpotLight.cpp // KRSpotLight.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name) KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
{ {
} }
KRSpotLight::~KRSpotLight() KRSpotLight::~KRSpotLight()
{ {
} }
std::string KRSpotLight::getElementName() { std::string KRSpotLight::getElementName() {
return "spot_light"; return "spot_light";
} }
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRLight::saveXML(parent); tinyxml2::XMLElement *e = KRLight::saveXML(parent);
e->SetAttribute("inner_angle", m_innerAngle); e->SetAttribute("inner_angle", m_innerAngle);
e->SetAttribute("outer_angle", m_outerAngle); e->SetAttribute("outer_angle", m_outerAngle);
return e; return e;
} }
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) { void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
KRLight::loadXML(e); KRLight::loadXML(e);
e->QueryFloatAttribute("inner_angle", &m_innerAngle); e->QueryFloatAttribute("inner_angle", &m_innerAngle);
e->QueryFloatAttribute("outer_angle", &m_outerAngle); e->QueryFloatAttribute("outer_angle", &m_outerAngle);
} }
float KRSpotLight::getInnerAngle() { float KRSpotLight::getInnerAngle() {
return m_innerAngle; return m_innerAngle;
} }
float KRSpotLight::getOuterAngle() { float KRSpotLight::getOuterAngle() {
return m_outerAngle; return m_outerAngle;
} }
void KRSpotLight::setInnerAngle(float innerAngle) { void KRSpotLight::setInnerAngle(float innerAngle) {
m_innerAngle = innerAngle; m_innerAngle = innerAngle;
} }
void KRSpotLight::setOuterAngle(float outerAngle) { void KRSpotLight::setOuterAngle(float outerAngle) {
m_outerAngle = outerAngle; m_outerAngle = outerAngle;
} }
AABB KRSpotLight::getBounds() { AABB KRSpotLight::getBounds() {
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE); float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
if(influence_radius < m_flareOcclusionSize) { if(influence_radius < m_flareOcclusionSize) {
influence_radius = m_flareOcclusionSize; influence_radius = m_flareOcclusionSize;
} }
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix()); return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
} }

View File

@@ -1,141 +1,141 @@
// //
// KRSprite.cpp // KRSprite.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 12-04-05. // Created by Kearwood Gilbert on 12-04-05.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRSprite.h" #include "KRSprite.h"
#include "KRNode.h" #include "KRNode.h"
#include "KRCamera.h" #include "KRCamera.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRShaderManager.h" #include "KRPipelineManager.h"
#include "KRShader.h" #include "KRPipeline.h"
#include "KRStockGeometry.h" #include "KRStockGeometry.h"
#include "KRDirectionalLight.h" #include "KRDirectionalLight.h"
#include "KRSpotLight.h" #include "KRSpotLight.h"
#include "KRPointLight.h" #include "KRPointLight.h"
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name) KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
{ {
m_spriteTexture = ""; m_spriteTexture = "";
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
m_spriteAlpha = 1.0f; m_spriteAlpha = 1.0f;
} }
KRSprite::~KRSprite() KRSprite::~KRSprite()
{ {
} }
std::string KRSprite::getElementName() { std::string KRSprite::getElementName() {
return "sprite"; return "sprite";
} }
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent) tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
{ {
tinyxml2::XMLElement *e = KRNode::saveXML(parent); tinyxml2::XMLElement *e = KRNode::saveXML(parent);
e->SetAttribute("sprite_texture", m_spriteTexture.c_str()); e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
e->SetAttribute("sprite_alpha", m_spriteAlpha); e->SetAttribute("sprite_alpha", m_spriteAlpha);
return e; return e;
} }
void KRSprite::loadXML(tinyxml2::XMLElement *e) { void KRSprite::loadXML(tinyxml2::XMLElement *e) {
KRNode::loadXML(e); KRNode::loadXML(e);
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) { if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
m_spriteAlpha = 1.0f; m_spriteAlpha = 1.0f;
} }
const char *szSpriteTexture = e->Attribute("sprite_texture"); const char *szSpriteTexture = e->Attribute("sprite_texture");
if(szSpriteTexture) { if(szSpriteTexture) {
m_spriteTexture = szSpriteTexture; m_spriteTexture = szSpriteTexture;
} else { } else {
m_spriteTexture = ""; m_spriteTexture = "";
} }
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
} }
void KRSprite::setSpriteTexture(std::string sprite_texture) { void KRSprite::setSpriteTexture(std::string sprite_texture) {
m_spriteTexture = sprite_texture; m_spriteTexture = sprite_texture;
m_pSpriteTexture = NULL; m_pSpriteTexture = NULL;
} }
void KRSprite::setSpriteAlpha(float alpha) void KRSprite::setSpriteAlpha(float alpha)
{ {
m_spriteAlpha = alpha; m_spriteAlpha = alpha;
} }
float KRSprite::getSpriteAlpha() const float KRSprite::getSpriteAlpha() const
{ {
return m_spriteAlpha; return m_spriteAlpha;
} }
AABB KRSprite::getBounds() { AABB KRSprite::getBounds() {
return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix()); return AABB::Create(-Vector3::One() * 0.5f, Vector3::One() * 0.5f, getModelMatrix());
} }
void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) { void KRSprite::render(KRCamera *pCamera, std::vector<KRPointLight *> &point_lights, std::vector<KRDirectionalLight *> &directional_lights, std::vector<KRSpotLight *>&spot_lights, const KRViewport &viewport, KRNode::RenderPass renderPass) {
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) { if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
// Pre-stream sprites, even if the alpha is zero // Pre-stream sprites, even if the alpha is zero
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) { if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
if(!m_pSpriteTexture && m_spriteTexture.size()) { if(!m_pSpriteTexture && m_spriteTexture.size()) {
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture); m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
} }
} }
if(m_pSpriteTexture) { if(m_pSpriteTexture) {
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE); m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
} }
} }
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return; if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass); KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) { if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) { if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
if(!m_pSpriteTexture && m_spriteTexture.size()) { if(!m_pSpriteTexture && m_spriteTexture.size()) {
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture); m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
} }
if(m_pSpriteTexture) { if(m_pSpriteTexture) {
/* /*
// Enable additive blending // Enable additive blending
GLDEBUG(glEnable(GL_BLEND)); GLDEBUG(glEnable(GL_BLEND));
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE)); GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
// Disable z-buffer write // Disable z-buffer write
GLDEBUG(glDepthMask(GL_FALSE)); GLDEBUG(glDepthMask(GL_FALSE));
*/ */
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes // TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
// Enable z-buffer test // Enable z-buffer test
GLDEBUG(glEnable(GL_DEPTH_TEST)); GLDEBUG(glEnable(GL_DEPTH_TEST));
GLDEBUG(glDepthFunc(GL_LEQUAL)); GLDEBUG(glDepthFunc(GL_LEQUAL));
GLDEBUG(glDepthRangef(0.0, 1.0)); GLDEBUG(glDepthRangef(0.0, 1.0));
// Render light sprite on transparency pass // Render light sprite on transparency pass
KRShader *pShader = getContext().getShaderManager()->getShader("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass); KRPipeline *pShader = getContext().getPipelineManager()->getPipeline("sprite", pCamera, point_lights, directional_lights, spot_lights, 0, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, renderPass);
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) { if(getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha); pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE); m_pContext->getTextureManager()->selectTexture(0, m_pSpriteTexture, 0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f); m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
} }
} }
} }
} }
} }

View File

@@ -1,60 +1,62 @@
// //
// KRStreamer.cpp // KRStreamer.cpp
// Kraken // Kraken
// //
// Created by Kearwood Gilbert on 11/1/2013. // Created by Kearwood Gilbert on 11/1/2013.
// Copyright (c) 2013 Kearwood Software. All rights reserved. // Copyright (c) 2013 Kearwood Software. All rights reserved.
// //
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRStreamer.h" #include "KRStreamer.h"
#include "KRContext.h" #include "KRContext.h"
#include <chrono> #include <chrono>
KRStreamer::KRStreamer(KRContext &context) : m_context(context) KRStreamer::KRStreamer(KRContext &context) : m_context(context)
{ {
m_running = false; m_running = false;
m_stop = false; m_stop = false;
} }
void KRStreamer::startStreamer() void KRStreamer::startStreamer()
{ {
if(!m_running) { if(!m_running) {
m_running = true; m_running = true;
KRContext::activateStreamerContext(); KRContext::activateStreamerContext();
m_thread = std::thread(&KRStreamer::run, this); m_thread = std::thread(&KRStreamer::run, this);
} }
} }
KRStreamer::~KRStreamer() KRStreamer::~KRStreamer()
{ {
if(m_running) { if(m_running) {
m_stop = true; m_stop = true;
m_thread.join(); m_thread.join();
m_running = false; m_running = false;
} }
} }
void KRStreamer::run() void KRStreamer::run()
{ {
#if defined(_WIN32) || defined(_WIN64) #if defined(ANDROID)
// TODO - Set thread names on windows // TODO - Set thread names on Android
#else #elif defined(_WIN32) || defined(_WIN64)
pthread_setname_np("Kraken - Streamer"); // TODO - Set thread names on windows
#endif #else
pthread_setname_np("Kraken - Streamer");
std::chrono::microseconds sleep_duration( 15000 ); #endif
KRContext::activateStreamerContext(); std::chrono::microseconds sleep_duration( 15000 );
while(!m_stop) KRContext::activateStreamerContext();
{
m_context.doStreaming(); while(!m_stop)
std::this_thread::sleep_for( sleep_duration ); {
} m_context.doStreaming();
} std::this_thread::sleep_for( sleep_duration );
}
}

View File

@@ -72,7 +72,7 @@ void KRTexture::resize(int max_dim)
m_iNewHandle = 0; m_iNewHandle = 0;
} else { } else {
int target_dim = max_dim; int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if(m_new_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) { if(m_new_lod_max_dim != target_dim || (m_iHandle == 0 && m_iNewHandle == 0)) {
assert(m_newTextureMemUsed == 0); assert(m_newTextureMemUsed == 0);
@@ -116,9 +116,9 @@ kraken_stream_level KRTexture::getStreamLevel(KRTexture::texture_usage_t texture
{ {
if(m_current_lod_max_dim == 0) { if(m_current_lod_max_dim == 0) {
return kraken_stream_level::STREAM_LEVEL_OUT; return kraken_stream_level::STREAM_LEVEL_OUT;
} else if(m_current_lod_max_dim == KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, m_max_lod_max_dim)) { } else if(m_current_lod_max_dim == KRMIN(getContext().KRENGINE_MAX_TEXTURE_DIM, (int)m_max_lod_max_dim)) {
return kraken_stream_level::STREAM_LEVEL_IN_HQ; return kraken_stream_level::STREAM_LEVEL_IN_HQ;
} else if(m_current_lod_max_dim >= KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, m_min_lod_max_dim)) { } else if(m_current_lod_max_dim >= KRMAX(getContext().KRENGINE_MIN_TEXTURE_DIM, (int)m_min_lod_max_dim)) {
return kraken_stream_level::STREAM_LEVEL_IN_LQ; return kraken_stream_level::STREAM_LEVEL_IN_LQ;
} else { } else {
return kraken_stream_level::STREAM_LEVEL_OUT; return kraken_stream_level::STREAM_LEVEL_OUT;

View File

@@ -43,13 +43,13 @@ KRTextureAnimated::KRTextureAnimated(KRContext &context, std::string name) : KRT
// - yy is the framerate // - yy is the framerate
// TODO - Add error handling for mal-formatted animated texture formats // TODO - Add error handling for mal-formatted animated texture formats
int first_comma_pos = name.find(","); size_t first_comma_pos = name.find(",");
int second_comma_pos = name.find(",", first_comma_pos + 1); size_t second_comma_pos = name.find(",", first_comma_pos + 1);
m_texture_base_name = name.substr(8, first_comma_pos - 8); m_texture_base_name = name.substr(8, first_comma_pos - 8);
m_frame_count = atoi(name.substr(first_comma_pos+1, second_comma_pos - first_comma_pos -1).c_str()); m_frame_count = atoi(name.substr(first_comma_pos+1, second_comma_pos - first_comma_pos -1).c_str());
m_frame_rate = atof(name.substr(second_comma_pos+1).c_str()); m_frame_rate = (float)atof(name.substr(second_comma_pos+1).c_str());
m_max_lod_max_dim = 2048; m_max_lod_max_dim = 2048;
m_min_lod_max_dim = 64; m_min_lod_max_dim = 64;
@@ -57,8 +57,8 @@ KRTextureAnimated::KRTextureAnimated(KRContext &context, std::string name) : KRT
for(int i=0; i<m_frame_count; i++) { for(int i=0; i<m_frame_count; i++) {
KRTexture2D *frame_texture = textureForFrame(i); KRTexture2D *frame_texture = textureForFrame(i);
if(frame_texture) { if(frame_texture) {
if(frame_texture->getMaxMipMap() < m_max_lod_max_dim) m_max_lod_max_dim = frame_texture->getMaxMipMap(); if(frame_texture->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = frame_texture->getMaxMipMap();
if(frame_texture->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = frame_texture->getMinMipMap(); if(frame_texture->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = frame_texture->getMinMipMap();
} }
} }
} }
@@ -106,7 +106,7 @@ void KRTextureAnimated::bind(GLuint texture_unit)
{ {
resetPoolExpiry(0.0f, TEXTURE_USAGE_NONE); // TODO - Need to set parameters here for streaming priority? resetPoolExpiry(0.0f, TEXTURE_USAGE_NONE); // TODO - Need to set parameters here for streaming priority?
KRTexture::bind(texture_unit); KRTexture::bind(texture_unit);
int frame_number = (int)floor(fmodf(getContext().getAbsoluteTime() * m_frame_rate,m_frame_count)); int frame_number = (int)floor(fmodf(getContext().getAbsoluteTime() * m_frame_rate, (float)m_frame_count));
KRTexture2D *frame_texture = textureForFrame(frame_number); KRTexture2D *frame_texture = textureForFrame(frame_number);
if(frame_texture) { if(frame_texture) {
frame_texture->bind(texture_unit); frame_texture->bind(texture_unit);

View File

@@ -44,8 +44,8 @@ KRTextureCube::KRTextureCube(KRContext &context, std::string name) : KRTexture(c
std::string faceName = getName() + SUFFIXES[i]; std::string faceName = getName() + SUFFIXES[i];
m_textures[i] = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName); m_textures[i] = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
if(m_textures[i]) { if(m_textures[i]) {
if(m_textures[i]->getMaxMipMap() < m_max_lod_max_dim) m_max_lod_max_dim = m_textures[i]->getMaxMipMap(); if(m_textures[i]->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = m_textures[i]->getMaxMipMap();
if(m_textures[i]->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap(); if(m_textures[i]->getMinMipMap() > (int)m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap();
} else { } else {
assert(false); assert(false);
} }
@@ -94,7 +94,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim)
long KRTextureCube::getMemRequiredForSize(int max_dim) long KRTextureCube::getMemRequiredForSize(int max_dim)
{ {
int target_dim = max_dim; int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
long memoryRequired = 0; long memoryRequired = 0;
for(int i=0; i<6; i++) { for(int i=0; i<6; i++) {

View File

@@ -59,7 +59,7 @@ KRTextureKTX::KRTextureKTX(KRContext &context, KRDataBlock *data, std::string na
uint32_t blockStart = sizeof(KTXHeader) + m_header.bytesOfKeyValueData; uint32_t blockStart = sizeof(KTXHeader) + m_header.bytesOfKeyValueData;
uint32_t width = m_header.pixelWidth, height = m_header.pixelHeight; uint32_t width = m_header.pixelWidth, height = m_header.pixelHeight;
for(int mipmap_level=0; mipmap_level < KRMAX(m_header.numberOfMipmapLevels, 1); mipmap_level++) { for(int mipmap_level=0; mipmap_level < (int)KRMAX(m_header.numberOfMipmapLevels, 1); mipmap_level++) {
uint32_t blockLength; uint32_t blockLength;
data->copy(&blockLength, blockStart, 4); data->copy(&blockLength, blockStart, 4);
blockStart += 4; blockStart += 4;
@@ -126,7 +126,7 @@ KRTextureKTX::~KRTextureKTX() {
long KRTextureKTX::getMemRequiredForSize(int max_dim) long KRTextureKTX::getMemRequiredForSize(int max_dim)
{ {
int target_dim = max_dim; int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = target_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = target_dim;
// Determine how much memory will be consumed // Determine how much memory will be consumed
@@ -137,7 +137,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
KRDataBlock *block = *itr; KRDataBlock *block = *itr;
if(width <= target_dim && height <= target_dim) { if(width <= target_dim && height <= target_dim) {
memoryRequired += block->getSize(); memoryRequired += (long)block->getSize();
} }
width = width >> 1; width = width >> 1;
@@ -156,7 +156,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha) bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha)
{ {
int target_dim = lod_max_dim; int target_dim = lod_max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if(m_blocks.size() == 0) { if(m_blocks.size() == 0) {
return false; return false;
@@ -239,9 +239,9 @@ bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
GLDEBUG(glCompressedTexImage2D(target, destination_level, (GLenum)m_header.glInternalFormat, width, height, 0, (GLsizei)block->getSize(), block->getStart())); GLDEBUG(glCompressedTexImage2D(target, destination_level, (GLenum)m_header.glInternalFormat, width, height, 0, (GLsizei)block->getSize(), block->getStart()));
#endif #endif
block->unlock(); block->unlock();
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE memoryTransferred += (long)block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
#endif #endif
memoryRequired += block->getSize(); memoryRequired += (long)block->getSize();
// //
// err = glGetError(); // err = glGetError();
// if (err != GL_NO_ERROR) { // if (err != GL_NO_ERROR) {

View File

@@ -40,7 +40,7 @@
#include "KRTextureAnimated.h" #include "KRTextureAnimated.h"
#include "KRContext.h" #include "KRContext.h"
KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context) { KRTextureManager::KRTextureManager(KRContext &context) : KRResourceManager(context) {
m_textureMemUsed = 0; m_textureMemUsed = 0;
for(int iTexture=0; iTexture<KRENGINE_MAX_TEXTURE_UNITS; iTexture++) { for(int iTexture=0; iTexture<KRENGINE_MAX_TEXTURE_UNITS; iTexture++) {
@@ -90,11 +90,13 @@ void KRTextureManager::_setWrapModeS(GLuint i, GLuint wrap_mode)
void KRTextureManager::_setMaxAnisotropy(int i, float max_anisotropy) void KRTextureManager::_setMaxAnisotropy(int i, float max_anisotropy)
{ {
#if !defined(ANDROID)
if(m_maxAnisotropy[i] != max_anisotropy) { if(m_maxAnisotropy[i] != max_anisotropy) {
_setActiveTexture(i); _setActiveTexture(i);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
m_maxAnisotropy[i] = max_anisotropy; m_maxAnisotropy[i] = max_anisotropy;
} }
#endif
} }
void KRTextureManager::setMaxAnisotropy(float max_anisotropy) void KRTextureManager::setMaxAnisotropy(float max_anisotropy)
@@ -113,6 +115,41 @@ void KRTextureManager::_setWrapModeT(GLuint i, GLuint wrap_mode)
} }
} }
KRResource* KRTextureManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
{
/*
} else if(extension.compare("pvr") == 0) {
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("ktx") == 0) {
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
} else if(extension.compare("tga") == 0) {
*/
if (extension.compare("pvr") == 0 ||
extension.compare("ktx") == 0 ||
extension.compare("tga") == 0) {
return loadTexture(name.c_str(), extension.c_str(), data);
}
return nullptr;
}
KRResource* KRTextureManager::getResource(const std::string& name, const std::string& extension)
{
if (extension.compare("pvr") == 0 ||
extension.compare("ktx") == 0 ||
extension.compare("tga") == 0) {
// TODO - Currently textures must have a unique name, without consideration
// of extensions. When textures are compressed, the uncompressed versions
// are removed. Both compressed and un-compressed textures should co-exist
// with the renderer prioritizing as necessary. This will facilitate more
// ergonomic usage within toolchain and editor GUI.
return getTexture(name);
}
return nullptr;
}
KRTexture *KRTextureManager::loadTexture(const char *szName, const char *szExtension, KRDataBlock *data) { KRTexture *KRTextureManager::loadTexture(const char *szName, const char *szExtension, KRDataBlock *data) {
KRTexture *pTexture = NULL; KRTexture *pTexture = NULL;

View File

@@ -34,6 +34,8 @@
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRResourceManager.h"
#include "KRTexture.h" #include "KRTexture.h"
#include "KRContextObject.h" #include "KRContextObject.h"
#include "KREngine-common.h" #include "KREngine-common.h"
@@ -41,10 +43,13 @@
#include "KRContext.h" #include "KRContext.h"
#include "KRStreamer.h" #include "KRStreamer.h"
class KRTextureManager : public KRContextObject { class KRTextureManager : public KRResourceManager {
public: public:
KRTextureManager(KRContext &context); KRTextureManager(KRContext &context);
virtual ~KRTextureManager(); virtual ~KRTextureManager();
virtual KRResource* loadResource(const std::string& name, const std::string& extension, KRDataBlock* data) override;
virtual KRResource* getResource(const std::string& name, const std::string& extension) override;
void selectTexture(int iTextureUnit, KRTexture *pTexture, float lod_coverage, KRTexture::texture_usage_t textureUsage); void selectTexture(int iTextureUnit, KRTexture *pTexture, float lod_coverage, KRTexture::texture_usage_t textureUsage);
bool selectTexture(GLenum target, int iTextureUnit, int iTextureHandle); bool selectTexture(GLenum target, int iTextureUnit, int iTextureHandle);

View File

@@ -147,7 +147,7 @@ KRTexturePVR::~KRTexturePVR() {
long KRTexturePVR::getMemRequiredForSize(int max_dim) long KRTexturePVR::getMemRequiredForSize(int max_dim)
{ {
int target_dim = max_dim; int target_dim = max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = target_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = target_dim;
// Determine how much memory will be consumed // Determine how much memory will be consumed
int width = m_iWidth; int width = m_iWidth;
@@ -157,7 +157,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) { for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
KRDataBlock *block = *itr; KRDataBlock *block = *itr;
if(width <= target_dim && height <= target_dim) { if(width <= target_dim && height <= target_dim) {
memoryRequired += block->getSize(); memoryRequired += (long)block->getSize();
} }
width = width >> 1; width = width >> 1;
@@ -176,7 +176,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha) bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha)
{ {
int target_dim = lod_max_dim; int target_dim = lod_max_dim;
if(target_dim < m_min_lod_max_dim) target_dim = m_min_lod_max_dim; if(target_dim < (int)m_min_lod_max_dim) target_dim = m_min_lod_max_dim;
if(m_blocks.size() == 0) { if(m_blocks.size() == 0) {
return false; return false;
@@ -256,12 +256,12 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int &current_lo
#if GL_EXT_texture_storage #if GL_EXT_texture_storage
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block->getSize(), block->getStart())); GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block->getSize(), block->getStart()));
#else #else
GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, block->getSize(), block->getStart())); GLDEBUG(glCompressedTexImage2D(target, destination_level, m_internalFormat, width, height, 0, (GLsizei)block->getSize(), block->getStart()));
#endif #endif
block->unlock(); block->unlock();
memoryTransferred += block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE memoryTransferred += (long)block->getSize(); // memoryTransferred does not include throughput of mipmap levels copied through glCopyTextureLevelsAPPLE
#endif #endif
memoryRequired += block->getSize(); memoryRequired += (long)block->getSize();
// //
// err = glGetError(); // err = glGetError();
// if (err != GL_NO_ERROR) { // if (err != GL_NO_ERROR) {

View File

@@ -1,385 +1,399 @@
// //
// KRTextureTGA.cpp // KRTextureTGA.cpp
// KREngine // KREngine
// //
// Created by Kearwood Gilbert on 2012-10-23. // Created by Kearwood Gilbert on 2012-10-23.
// Copyright (c) 2012 Kearwood Software. All rights reserved. // Copyright (c) 2012 Kearwood Software. All rights reserved.
// //
#include "KRTextureTGA.h" #include "KRTextureTGA.h"
#include "KREngine-common.h" #include "KREngine-common.h"
#include "KRContext.h" #include "KRContext.h"
#include "KRTextureKTX.h" #include "KRTextureKTX.h"
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
#pragma pack(1) #pragma pack(1)
typedef struct { typedef struct {
char idlength; char idlength;
char colourmaptype; char colourmaptype;
char imagetype; char imagetype;
short int colourmaporigin; short int colourmaporigin;
short int colourmaplength; short int colourmaplength;
char colourmapdepth; char colourmapdepth;
short int x_origin; short int x_origin;
short int y_origin; short int y_origin;
short width; short width;
short height; short height;
char bitsperpixel; char bitsperpixel;
char imagedescriptor; char imagedescriptor;
} TGA_HEADER; } TGA_HEADER;
#pragma pack() #pragma pack()
#else #else
typedef struct { typedef struct {
char idlength; char idlength;
char colourmaptype; char colourmaptype;
char imagetype; char imagetype;
short int colourmaporigin; short int colourmaporigin;
short int colourmaplength; short int colourmaplength;
char colourmapdepth; char colourmapdepth;
short int x_origin; short int x_origin;
short int y_origin; short int y_origin;
short width; short width;
short height; short height;
char bitsperpixel; char bitsperpixel;
char imagedescriptor; char imagedescriptor;
} __attribute__((packed)) TGA_HEADER; } __attribute__((packed)) TGA_HEADER;
#endif #endif
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name) KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
{ {
data->lock(); data->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart(); TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height; m_max_lod_max_dim = pHeader->width > pHeader->height ? pHeader->width : pHeader->height;
m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images m_min_lod_max_dim = m_max_lod_max_dim; // Mipmaps not yet supported for TGA images
switch(pHeader->imagetype) { switch(pHeader->imagetype) {
case 2: // rgb case 2: // rgb
case 10: // rgb + rle case 10: // rgb + rle
switch(pHeader->bitsperpixel) { switch(pHeader->bitsperpixel) {
case 24: case 24:
{ {
m_imageSize = pHeader->width * pHeader->height * 4; m_imageSize = pHeader->width * pHeader->height * 4;
} }
break; break;
case 32: case 32:
{ {
m_imageSize = pHeader->width * pHeader->height * 4; m_imageSize = pHeader->width * pHeader->height * 4;
} }
break; break;
default: default:
{ {
assert(false); assert(false);
} }
break; break;
} }
break; break;
default: default:
{ {
assert(false); assert(false);
break; break;
} }
} }
data->unlock(); data->unlock();
} }
KRTextureTGA::~KRTextureTGA() KRTextureTGA::~KRTextureTGA()
{ {
} }
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha) bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress, bool premultiply_alpha)
{ {
m_pData->lock(); m_pData->lock();
TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart(); TGA_HEADER *pHeader = (TGA_HEADER *)m_pData->getStart();
unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER); unsigned char *pData = (unsigned char *)pHeader + (long)pHeader->idlength + (long)pHeader->colourmaplength * (long)pHeader->colourmaptype + sizeof(TGA_HEADER);
GLenum internal_format = GL_RGBA; GLenum internal_format = GL_RGBA;
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE && !defined(ANDROID)
if(compress) { if(compress) {
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
} }
#endif #endif
if(pHeader->colourmaptype != 0) { if(pHeader->colourmaptype != 0) {
m_pData->unlock(); m_pData->unlock();
return false; // Mapped colors not supported return false; // Mapped colors not supported
} }
switch(pHeader->imagetype) { switch(pHeader->imagetype) {
case 2: // rgb case 2: // rgb
switch(pHeader->bitsperpixel) { switch(pHeader->bitsperpixel) {
case 24: case 24:
{ {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
//#ifdef __APPLE__ //#ifdef __APPLE__
// vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 }; // vImage_Buffer source_image = { pData, pHeader->height, pHeader->width, pHeader->width*3 };
// vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 }; // vImage_Buffer dest_image = { converted_image, pHeader->height, pHeader->width, pHeader->width*4 };
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile); // vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
//#else //#else
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
while(pSource < pEnd) { while(pSource < pEnd) {
*pDest++ = pSource[0]; *pDest++ = pSource[2];
*pDest++ = pSource[1]; *pDest++ = pSource[1];
*pDest++ = pSource[2]; *pDest++ = pSource[0];
*pDest++ = 0xff; *pDest++ = 0xff;
pSource += 3; pSource += 3;
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
//#endif //#endif
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
current_lod_max_dim = m_max_lod_max_dim; current_lod_max_dim = m_max_lod_max_dim;
} }
break; break;
case 32: case 32:
{ {
if(premultiply_alpha) { if(premultiply_alpha) {
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
unsigned char *pSource = pData; unsigned char *pSource = pData;
unsigned char *pDest = converted_image; unsigned char *pDest = converted_image;
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
while(pSource < pEnd) { while(pSource < pEnd) {
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = pSource[3]; *pDest++ = pSource[3];
pSource += 4; pSource += 4;
} }
assert(pSource <= m_pData->getEnd()); assert(pSource <= m_pData->getEnd());
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish()); GLDEBUG(glFinish());
free(converted_image); free(converted_image);
} else { } else {
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData)); unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
GLDEBUG(glFinish());
} unsigned char *pSource = pData;
unsigned char *pDest = converted_image;
current_lod_max_dim = m_max_lod_max_dim; unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
} while(pSource < pEnd) {
break; *pDest++ = (__uint32_t)pSource[2];
default: *pDest++ = (__uint32_t)pSource[1];
m_pData->unlock(); *pDest++ = (__uint32_t)pSource[0];
return false; // 16-bit images not yet supported *pDest++ = pSource[3];
} pSource += 4;
break; }
case 10: // rgb + rle assert(pSource <= m_pData->getEnd());
switch(pHeader->bitsperpixel) { GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
case 32: GLDEBUG(glFinish());
{ free(converted_image);
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); }
unsigned char *pSource = pData;
unsigned char *pDest = converted_image; current_lod_max_dim = m_max_lod_max_dim;
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4; }
if(premultiply_alpha) { break;
while(pDest < pEnd) { default:
int count = (*pSource & 0x7f) + 1; m_pData->unlock();
if(*pSource & 0x80) { return false; // 16-bit images not yet supported
// RLE Packet }
pSource++; break;
while(count--) { case 10: // rgb + rle
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; switch(pHeader->bitsperpixel) {
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; case 32:
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; {
*pDest++ = pSource[3]; unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
} unsigned char *pSource = pData;
pSource += 4; unsigned char *pDest = converted_image;
} else { unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
// RAW Packet if(premultiply_alpha) {
pSource++; while(pDest < pEnd) {
while(count--) { int count = (*pSource & 0x7f) + 1;
*pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff; if(*pSource & 0x80) {
*pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff; // RLE Packet
*pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff; pSource++;
*pDest++ = pSource[3]; while(count--) {
pSource += 4; *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
} *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
} *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
} *pDest++ = pSource[3];
assert(pSource <= m_pData->getEnd()); }
assert(pDest == pEnd); pSource += 4;
} else { } else {
while(pDest < pEnd) { // RAW Packet
int count = (*pSource & 0x7f) + 1; pSource++;
if(*pSource & 0x80) { while(count--) {
// RLE Packet *pDest++ = (__uint32_t)pSource[2] * (__uint32_t)pSource[3] / 0xff;
pSource++; *pDest++ = (__uint32_t)pSource[1] * (__uint32_t)pSource[3] / 0xff;
while(count--) { *pDest++ = (__uint32_t)pSource[0] * (__uint32_t)pSource[3] / 0xff;
*pDest++ = pSource[0]; *pDest++ = pSource[3];
*pDest++ = pSource[1]; pSource += 4;
*pDest++ = pSource[2]; }
*pDest++ = pSource[3]; }
} }
pSource += 4; assert(pSource <= m_pData->getEnd());
} else { assert(pDest == pEnd);
// RAW Packet } else {
pSource++; while(pDest < pEnd) {
while(count--) { int count = (*pSource & 0x7f) + 1;
*pDest++ = pSource[0]; if(*pSource & 0x80) {
*pDest++ = pSource[1]; // RLE Packet
*pDest++ = pSource[2]; pSource++;
*pDest++ = pSource[3]; while(count--) {
pSource += 4; *pDest++ = pSource[2];
} *pDest++ = pSource[1];
} *pDest++ = pSource[0];
} *pDest++ = pSource[3];
assert(pSource <= m_pData->getEnd()); }
assert(pDest == pEnd); pSource += 4;
} } else {
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); // RAW Packet
GLDEBUG(glFinish()); pSource++;
free(converted_image); while(count--) {
current_lod_max_dim = m_max_lod_max_dim; *pDest++ = pSource[2];
} *pDest++ = pSource[1];
break; *pDest++ = pSource[0];
case 24: *pDest++ = pSource[3];
{ pSource += 4;
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4); }
unsigned char *pSource = pData; }
unsigned char *pDest = converted_image; }
unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4; assert(pSource <= m_pData->getEnd());
while(pDest < pEnd) { assert(pDest == pEnd);
int count = (*pSource & 0x7f) + 1; }
if(*pSource & 0x80) { GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
// RLE Packet GLDEBUG(glFinish());
pSource++; free(converted_image);
while(count--) { current_lod_max_dim = m_max_lod_max_dim;
*pDest++ = pSource[0]; }
*pDest++ = pSource[1]; break;
*pDest++ = pSource[2]; case 24:
*pDest++ = 0xff; {
} unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
pSource += 3; unsigned char *pSource = pData;
} else { unsigned char *pDest = converted_image;
// RAW Packet unsigned char *pEnd = converted_image + pHeader->height * pHeader->width * 4;
pSource++; while(pDest < pEnd) {
while(count--) { int count = (*pSource & 0x7f) + 1;
*pDest++ = pSource[0]; if(*pSource & 0x80) {
*pDest++ = pSource[1]; // RLE Packet
*pDest++ = pSource[2]; pSource++;
*pDest++ = 0xff; while(count--) {
pSource += 3; *pDest++ = pSource[2];
} *pDest++ = pSource[1];
} *pDest++ = pSource[0];
} *pDest++ = 0xff;
assert(pSource <= m_pData->getEnd()); }
assert(pDest == pEnd); pSource += 3;
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image)); } else {
GLDEBUG(glFinish()); // RAW Packet
free(converted_image); pSource++;
current_lod_max_dim = m_max_lod_max_dim; while(count--) {
} *pDest++ = pSource[2];
break; *pDest++ = pSource[1];
default: *pDest++ = pSource[0];
m_pData->unlock(); *pDest++ = 0xff;
return false; // 16-bit images not yet supported pSource += 3;
} }
break; }
default: }
m_pData->unlock(); assert(pSource <= m_pData->getEnd());
return false; // Image type not yet supported assert(pDest == pEnd);
} GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
GLDEBUG(glFinish());
m_pData->unlock(); free(converted_image);
return true; current_lod_max_dim = m_max_lod_max_dim;
} }
break;
#if !TARGET_OS_IPHONE default:
m_pData->unlock();
KRTexture *KRTextureTGA::compress(bool premultiply_alpha) return false; // 16-bit images not yet supported
{ }
m_pData->lock(); break;
default:
std::list<KRDataBlock *> blocks; m_pData->unlock();
return false; // Image type not yet supported
getContext().getTextureManager()->_setActiveTexture(0); }
GLuint compressed_handle = 0; m_pData->unlock();
GLDEBUG(glGenTextures(1, &compressed_handle)); return true;
}
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
#if !TARGET_OS_IPHONE && !defined(ANDROID)
int current_max_dim = 0;
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) { KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
assert(false); // Failed to upload the texture {
} m_pData->lock();
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
std::list<KRDataBlock *> blocks;
GLint width = 0, height = 0, internal_format, base_internal_format;
getContext().getTextureManager()->_setActiveTexture(0);
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width)); GLuint compressed_handle = 0;
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height)); GLDEBUG(glGenTextures(1, &compressed_handle));
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
/*
int texture_base_level = 0; int current_max_dim = 0;
int texture_max_level = 0; if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level)); assert(false); // Failed to upload the texture
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level)); }
*/ GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
switch(internal_format)
{ GLint width = 0, height = 0, internal_format, base_internal_format;
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
base_internal_format = GL_BGRA;
break; GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
base_internal_format = GL_BGRA; GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
break;
default: /*
assert(false); // Not yet supported int texture_base_level = 0;
break; int texture_max_level = 0;
} GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, &texture_base_level));
GLDEBUG(glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, &texture_max_level));
GLuint lod_level = 0; */
GLint compressed_size = 0; switch(internal_format)
int lod_width = width; {
while(lod_width > 1) { case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width)); base_internal_format = GL_BGRA;
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size)); break;
KRDataBlock *new_block = new KRDataBlock(); case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
new_block->expand(compressed_size); base_internal_format = GL_BGRA;
new_block->lock(); break;
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart())); default:
new_block->unlock(); assert(false); // Not yet supported
blocks.push_back(new_block); break;
}
lod_level++;
} GLuint lod_level = 0;
assert(lod_width == 1); GLint compressed_size = 0;
int lod_width = width;
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0)); while(lod_width > 1) {
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
GLDEBUG(glDeleteTextures(1, &compressed_handle)); GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
KRDataBlock *new_block = new KRDataBlock();
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks); new_block->expand(compressed_size);
new_block->lock();
m_pData->unlock(); GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
new_block->unlock();
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) { blocks.push_back(new_block);
KRDataBlock *block = *block_itr;
delete block; lod_level++;
} }
assert(lod_width == 1);
return new_texture;
} GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
#endif getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
GLDEBUG(glDeleteTextures(1, &compressed_handle));
long KRTextureTGA::getMemRequiredForSize(int max_dim)
{ KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
return m_imageSize;
} m_pData->unlock();
std::string KRTextureTGA::getExtension() for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
{ KRDataBlock *block = *block_itr;
return "tga"; delete block;
} }
return new_texture;
}
#endif
long KRTextureTGA::getMemRequiredForSize(int max_dim)
{
return m_imageSize;
}
std::string KRTextureTGA::getExtension()
{
return "tga";
}

View File

@@ -20,7 +20,7 @@ public:
bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress = false, bool premultiply_alpha = false); bool uploadTexture(GLenum target, int lod_max_dim, int &current_lod_max_dim, bool compress = false, bool premultiply_alpha = false);
#if !TARGET_OS_IPHONE #if !TARGET_OS_IPHONE && !defined(ANDROID)
virtual KRTexture *compress(bool premultiply_alpha = false); virtual KRTexture *compress(bool premultiply_alpha = false);
#endif #endif

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