Merge pull request #1 from KrakenEngine/feature-vulkan
Feature vulkan merged to master. Work to continue there
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -7,3 +7,6 @@
|
||||
[submodule "hydra"]
|
||||
path = hydra
|
||||
url = git@github.com:KrakenEngine/hydra.git
|
||||
[submodule "3rdparty/glslang"]
|
||||
path = 3rdparty/glslang
|
||||
url = git@github.com:KhronosGroup/glslang.git
|
||||
|
||||
@@ -3,7 +3,7 @@ compiler: clang
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- feature-vulkan
|
||||
|
||||
matrix:
|
||||
include:
|
||||
@@ -14,7 +14,6 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- libc++-dev
|
||||
- libboost-dev
|
||||
- os: osx
|
||||
osx_image: xcode9.1
|
||||
|
||||
|
||||
1
3rdparty/glslang
vendored
Submodule
1
3rdparty/glslang
vendored
Submodule
Submodule 3rdparty/glslang added at 83af469512
146
CMakeLists.txt
146
CMakeLists.txt
@@ -1,9 +1,17 @@
|
||||
cmake_minimum_required (VERSION 2.6)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
|
||||
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++")
|
||||
endif()
|
||||
|
||||
@@ -27,6 +35,21 @@ macro (add_sources)
|
||||
endif()
|
||||
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)
|
||||
file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
foreach (_src ${ARGN})
|
||||
@@ -43,6 +66,8 @@ macro (add_public_header)
|
||||
endmacro()
|
||||
|
||||
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)
|
||||
# INCLUDE_DIRECTORIES ( /Developer/Headers/FlatCarbon )
|
||||
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/vector2i.h)
|
||||
|
||||
add_library(kraken SHARED ${SRCS} ${KRAKEN_PUBLIC_HEADERS})
|
||||
|
||||
set(Boost_USE_STATIC_LIBS ON) # only find static libs
|
||||
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})
|
||||
# ---- Android ----
|
||||
if(ANDROID)
|
||||
add_subdirectory(kraken_android)
|
||||
endif()
|
||||
|
||||
# ---- Hydra ----
|
||||
add_subdirectory(hydra)
|
||||
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 ----
|
||||
if(ANDROID)
|
||||
list (APPEND EXTRA_LIBS "EGL")
|
||||
list (APPEND EXTRA_LIBS "GLESv3")
|
||||
else()
|
||||
find_package(OpenGL REQUIRED)
|
||||
include_directories( ${OPENGL_INCLUDE_DIRS} )
|
||||
target_link_libraries(kraken ${OPENGL_LIBRARIES})
|
||||
list (APPEND EXTRA_LIBS "${OPENGL_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
# ---- 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)
|
||||
add_subdirectory(3rdparty/glad)
|
||||
include_directories(${GLAD_INCLUDE_DIRS})
|
||||
target_link_libraries(kraken glad)
|
||||
list (APPEND EXTRA_LIBS "glad")
|
||||
endif()
|
||||
|
||||
# ---- GLFW ----
|
||||
if(NOT ANDROID)
|
||||
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_DOCS OFF CACHE INTERNAL "Build the GLFW documentation")
|
||||
set(GLFW_INSTALL OFF CACHE INTERNAL "Generate installation target")
|
||||
add_subdirectory(3rdparty/glfw)
|
||||
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} )
|
||||
SET_TARGET_PROPERTIES(
|
||||
kraken
|
||||
PROPERTIES
|
||||
FRAMEWORK ON
|
||||
SOVERSION 0
|
||||
VERSION 0.1.0
|
||||
PUBLIC_HEADER "${KRAKEN_PUBLIC_HEADERS}"
|
||||
PRIVATE_HEADER "${PRIVATE_HEADER_FILES}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "archive"
|
||||
LIBRARY_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "lib${LIB_SUFFIX}"
|
||||
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
|
||||
# COMMENT "Compressing..."
|
||||
# WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/archive"
|
||||
# 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
41
CMakeSettings.json
Normal 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
1
configure_macos.sh
Executable 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
2
configure_win64.bat
Normal 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
2
configure_win64_msvc.bat
Normal 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
2
hydra
Submodule hydra updated: 5cca3a9fb1...dff00680fa
@@ -3,6 +3,7 @@ add_subdirectory(public)
|
||||
set(KRAKEN_PUBLIC_HEADERS "${KRAKEN_PUBLIC_HEADERS}" PARENT_SCOPE)
|
||||
|
||||
# Private Implementation
|
||||
add_sources(kraken.cpp)
|
||||
add_sources(KRAmbientZone.cpp)
|
||||
add_sources(KRAnimation.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+obj.cpp)
|
||||
add_sources(KRResource.cpp)
|
||||
add_sources(KRResourceManager.cpp)
|
||||
add_sources(KRReverbZone.cpp)
|
||||
add_sources(KRScene.cpp)
|
||||
add_sources(KRSceneManager.cpp)
|
||||
add_sources(KRShader.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(KRSprite.cpp)
|
||||
add_sources(KRTexture.cpp)
|
||||
|
||||
@@ -1,167 +1,167 @@
|
||||
//
|
||||
// KRAmbientZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAmbientZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_ambient = "";
|
||||
m_ambient_gain = 1.0f;
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRAmbientZone::~KRAmbientZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getElementName() {
|
||||
return "ambient_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_ambient.c_str());
|
||||
e->SetAttribute("gain", m_ambient_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_ambient = e->Attribute("sample");
|
||||
|
||||
m_ambient_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_ambient_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getAmbient()
|
||||
{
|
||||
return m_ambient;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
||||
{
|
||||
m_ambient = ambient;
|
||||
}
|
||||
|
||||
float KRAmbientZone::getAmbientGain()
|
||||
{
|
||||
return m_ambient_gain;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
||||
{
|
||||
m_ambient_gain = ambient_gain;
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAmbientZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRAmbientZone::getBounds() {
|
||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
//
|
||||
// KRAmbientZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRAmbientZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRAmbientZone::KRAmbientZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_ambient = "";
|
||||
m_ambient_gain = 1.0f;
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRAmbientZone::~KRAmbientZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getElementName() {
|
||||
return "ambient_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRAmbientZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_ambient.c_str());
|
||||
e->SetAttribute("gain", m_ambient_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRAmbientZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_ambient = e->Attribute("sample");
|
||||
|
||||
m_ambient_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_ambient_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_ambient_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getAmbient()
|
||||
{
|
||||
return m_ambient;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbient(const std::string &ambient)
|
||||
{
|
||||
m_ambient = ambient;
|
||||
}
|
||||
|
||||
float KRAmbientZone::getAmbientGain()
|
||||
{
|
||||
return m_ambient_gain;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setAmbientGain(float ambient_gain)
|
||||
{
|
||||
m_ambient_gain = ambient_gain;
|
||||
}
|
||||
|
||||
std::string KRAmbientZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_AMBIENT_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pPipeline, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRAmbientZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRAmbientZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRAmbientZone::getBounds() {
|
||||
// Ambient zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRAmbientZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,6 @@
|
||||
// authors and should not be interpreted as representing official policies, either expressed
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "KRAnimation.h"
|
||||
#include "KRAnimationManager.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());
|
||||
KRAnimationCurve *new_curve = curve;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "KRAnimationCurveManager.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;
|
||||
}
|
||||
|
||||
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 *pAnimationCurve = KRAnimationCurve::Load(*m_pContext, name, data);
|
||||
if(pAnimationCurve) {
|
||||
|
||||
@@ -34,17 +34,22 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRAnimationCurve.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
using std::map;
|
||||
|
||||
class KRAnimationCurveManager : public KRContextObject {
|
||||
class KRAnimationCurveManager : public KRResourceManager {
|
||||
public:
|
||||
KRAnimationCurveManager(KRContext &context);
|
||||
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 *getAnimationCurve(const std::string &name);
|
||||
void addAnimationCurve(KRAnimationCurve *new_animation_curve);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#include "KRAnimationManager.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 *pAnimation = KRAnimation::Load(*m_pContext, szName, data);
|
||||
|
||||
@@ -34,16 +34,21 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRAnimation.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
|
||||
|
||||
class KRAnimationManager : public KRContextObject {
|
||||
class KRAnimationManager : public KRResourceManager {
|
||||
public:
|
||||
KRAnimationManager(KRContext &context);
|
||||
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 *getAnimation(const char *szName);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRAudioSource.h"
|
||||
@@ -90,10 +92,13 @@ typedef struct {
|
||||
KRAudioSample *reverb_sample;
|
||||
} siren_reverb_zone_weight_info;
|
||||
|
||||
class KRAudioManager : public KRContextObject {
|
||||
class KRAudioManager : public KRResourceManager {
|
||||
public:
|
||||
KRAudioManager(KRContext &context);
|
||||
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();
|
||||
|
||||
@@ -238,7 +243,7 @@ private:
|
||||
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
|
||||
|
||||
boost::signals2::mutex m_mutex;
|
||||
std::mutex m_mutex;
|
||||
#ifdef __APPLE__
|
||||
mach_timebase_info_data_t m_timebase_info;
|
||||
#endif
|
||||
|
||||
@@ -84,7 +84,7 @@ int KRAudioSample::getChannelCount()
|
||||
return m_channelsPerFrame;
|
||||
}
|
||||
|
||||
int KRAudioSample::getFrameCount()
|
||||
__int64_t KRAudioSample::getFrameCount()
|
||||
{
|
||||
loadInfo();
|
||||
//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) {
|
||||
return 0.0f; // Past the end of the recording
|
||||
} 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);
|
||||
if(buffer == NULL) {
|
||||
@@ -132,12 +132,12 @@ void KRAudioSample::sample(__int64_t frame_offset, int frame_count, int channel,
|
||||
{
|
||||
loadInfo();
|
||||
|
||||
m_last_frame_used = getContext().getAudioManager()->getAudioFrame();
|
||||
m_last_frame_used = (int)getContext().getAudioManager()->getAudioFrame();
|
||||
|
||||
if(loop) {
|
||||
int buffer_offset = 0;
|
||||
int frames_left = frame_count;
|
||||
int sample_length = getFrameCount();
|
||||
int sample_length = (int)getFrameCount();
|
||||
while(frames_left) {
|
||||
int next_frame = (int)(((__int64_t)frame_offset + (__int64_t)buffer_offset) % 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
|
||||
memset(buffer, 0, frame_count * sizeof(float));
|
||||
} else {
|
||||
int start_frame = frame_offset < 0 ? 0 : frame_offset;
|
||||
int prefix_frames = frame_offset < 0 ? -frame_offset : 0;
|
||||
int start_frame = (int)(frame_offset < 0 ? 0 : frame_offset);
|
||||
int prefix_frames = (int)(frame_offset < 0 ? -frame_offset : 0);
|
||||
if(prefix_frames > 0) {
|
||||
// Prefix with padding of 0's
|
||||
memset(buffer, 0, prefix_frames * sizeof(float));
|
||||
@@ -386,7 +386,7 @@ KRAudioBuffer *KRAudioSample::getBuffer(int index)
|
||||
void KRAudioSample::_endFrame()
|
||||
{
|
||||
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) {
|
||||
closeFile();
|
||||
}
|
||||
|
||||
@@ -1,113 +1,113 @@
|
||||
//
|
||||
// KRAudioSample.h
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef KRAUDIOSAMPLE_H
|
||||
#define KRAUDIOSAMPLE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRResource.h"
|
||||
|
||||
class KRAudioBuffer;
|
||||
|
||||
class KRAudioSample : public KRResource {
|
||||
|
||||
public:
|
||||
KRAudioSample(KRContext &context, std::string name, std::string extension);
|
||||
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
|
||||
virtual ~KRAudioSample();
|
||||
|
||||
virtual std::string getExtension();
|
||||
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
float getDuration();
|
||||
KRAudioBuffer *getBuffer(int index);
|
||||
int getBufferCount();
|
||||
|
||||
// Siren audio engine interface
|
||||
int getChannelCount();
|
||||
int getFrameCount();
|
||||
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 _endFrame();
|
||||
private:
|
||||
|
||||
long m_last_frame_used;
|
||||
|
||||
std::string m_extension;
|
||||
KRDataBlock *m_pData;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Apple Audio Toolbox
|
||||
AudioFileID m_audio_file_id;
|
||||
ExtAudioFileRef m_fileRef;
|
||||
|
||||
static OSStatus ReadProc( // AudioFile_ReadProc
|
||||
void * inClientData,
|
||||
SInt64 inPosition,
|
||||
UInt32 requestCount,
|
||||
void * buffer,
|
||||
UInt32 * actualCount);
|
||||
|
||||
static OSStatus WriteProc( // AudioFile_WriteProc
|
||||
void * inClientData,
|
||||
SInt64 inPosition,
|
||||
UInt32 requestCount,
|
||||
const void *buffer,
|
||||
UInt32 * actualCount);
|
||||
|
||||
static SInt64 GetSizeProc( // AudioFile_GetSizeProc
|
||||
void * inClientData);
|
||||
|
||||
|
||||
static OSStatus SetSizeProc( // AudioFile_SetSizeProc
|
||||
void * inClientData,
|
||||
SInt64 inSize);
|
||||
#endif
|
||||
|
||||
int m_bufferCount;
|
||||
|
||||
__int64_t m_totalFrames;
|
||||
int m_frameRate;
|
||||
int m_bytesPerFrame;
|
||||
int m_channelsPerFrame;
|
||||
|
||||
void openFile();
|
||||
void closeFile();
|
||||
void loadInfo();
|
||||
|
||||
static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
|
||||
};
|
||||
|
||||
#endif /* defined(KRAUDIOSAMPLE_H) */
|
||||
//
|
||||
// KRAudioSample.h
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef KRAUDIOSAMPLE_H
|
||||
#define KRAUDIOSAMPLE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRResource.h"
|
||||
|
||||
class KRAudioBuffer;
|
||||
|
||||
class KRAudioSample : public KRResource {
|
||||
|
||||
public:
|
||||
KRAudioSample(KRContext &context, std::string name, std::string extension);
|
||||
KRAudioSample(KRContext &context, std::string name, std::string extension, KRDataBlock *data);
|
||||
virtual ~KRAudioSample();
|
||||
|
||||
virtual std::string getExtension();
|
||||
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
float getDuration();
|
||||
KRAudioBuffer *getBuffer(int index);
|
||||
int getBufferCount();
|
||||
|
||||
// Siren audio engine interface
|
||||
int getChannelCount();
|
||||
__int64_t getFrameCount();
|
||||
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 _endFrame();
|
||||
private:
|
||||
|
||||
__int64_t m_last_frame_used;
|
||||
|
||||
std::string m_extension;
|
||||
KRDataBlock *m_pData;
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Apple Audio Toolbox
|
||||
AudioFileID m_audio_file_id;
|
||||
ExtAudioFileRef m_fileRef;
|
||||
|
||||
static OSStatus ReadProc( // AudioFile_ReadProc
|
||||
void * inClientData,
|
||||
SInt64 inPosition,
|
||||
UInt32 requestCount,
|
||||
void * buffer,
|
||||
UInt32 * actualCount);
|
||||
|
||||
static OSStatus WriteProc( // AudioFile_WriteProc
|
||||
void * inClientData,
|
||||
SInt64 inPosition,
|
||||
UInt32 requestCount,
|
||||
const void *buffer,
|
||||
UInt32 * actualCount);
|
||||
|
||||
static SInt64 GetSizeProc( // AudioFile_GetSizeProc
|
||||
void * inClientData);
|
||||
|
||||
|
||||
static OSStatus SetSizeProc( // AudioFile_SetSizeProc
|
||||
void * inClientData,
|
||||
SInt64 inSize);
|
||||
#endif
|
||||
|
||||
int m_bufferCount;
|
||||
|
||||
__int64_t m_totalFrames;
|
||||
int m_frameRate;
|
||||
int m_bytesPerFrame;
|
||||
int m_channelsPerFrame;
|
||||
|
||||
void openFile();
|
||||
void closeFile();
|
||||
void loadInfo();
|
||||
|
||||
static void PopulateBuffer(KRAudioSample *sound, int index, void *data);
|
||||
};
|
||||
|
||||
#endif /* defined(KRAUDIOSAMPLE_H) */
|
||||
|
||||
@@ -180,9 +180,9 @@ void KRAudioSource::render(KRCamera *pCamera, std::vector<KRPointLight *> &point
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
@@ -433,7 +433,7 @@ float KRAudioSource::getAudioTime()
|
||||
void KRAudioSource::setAudioTime(float new_position)
|
||||
{
|
||||
// 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)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#define KRBEHAVIOR_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
|
||||
|
||||
@@ -1,97 +1,97 @@
|
||||
//
|
||||
// KRBone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRBone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
KRBone::~KRBone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRBone::getElementName() {
|
||||
return "bone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
AABB KRBone::getBounds() {
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer 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);
|
||||
|
||||
if(getContext().getShaderManager()->selectShader(*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");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRBone::setBindPose(const Matrix4 &pose)
|
||||
{
|
||||
m_bind_pose = pose;
|
||||
}
|
||||
const Matrix4 &KRBone::getBindPose()
|
||||
{
|
||||
return m_bind_pose;
|
||||
}
|
||||
//
|
||||
// KRBone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRBone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRBone::KRBone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
KRBone::~KRBone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRBone::getElementName() {
|
||||
return "bone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRBone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRBone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
setScaleCompensation(true);
|
||||
}
|
||||
|
||||
AABB KRBone::getBounds() {
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_BONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
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().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");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KRBone::setBindPose(const Matrix4 &pose)
|
||||
{
|
||||
m_bind_pose = pose;
|
||||
}
|
||||
const Matrix4 &KRBone::getBindPose()
|
||||
{
|
||||
return m_bind_pose;
|
||||
}
|
||||
|
||||
@@ -54,14 +54,14 @@ KRBundle::KRBundle(KRContext &context, std::string name, KRDataBlock *pData) : K
|
||||
m_pData = pData;
|
||||
|
||||
__int64_t file_pos = 0;
|
||||
while(file_pos < m_pData->getSize()) {
|
||||
while(file_pos < (__int64_t)m_pData->getSize()) {
|
||||
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);
|
||||
file_pos += 512; // Skip past the header to the file contents
|
||||
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
|
||||
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);
|
||||
}
|
||||
file_pos += RoundUpSize(file_size);
|
||||
@@ -114,7 +114,7 @@ bool KRBundle::save(KRDataBlock &data) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRBundle::append(KRResource &resource)
|
||||
KRDataBlock* KRBundle::append(KRResource &resource)
|
||||
{
|
||||
// Serialize resource to binary representation
|
||||
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
|
||||
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->lock();
|
||||
@@ -163,4 +163,7 @@ void KRBundle::append(KRResource &resource)
|
||||
sprintf(file_header->checksum, "%07o", check_sum);
|
||||
|
||||
m_pData->unlock();
|
||||
|
||||
KRDataBlock *pFileData = m_pData->getSubBlock((int)resource_data_start, (int)resource_data.getSize());
|
||||
return pFileData;
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
void append(KRResource &resource);
|
||||
KRDataBlock* append(KRResource &resource);
|
||||
|
||||
private:
|
||||
KRDataBlock *m_pData;
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
#include "KRBundle.h"
|
||||
|
||||
KRBundleManager::KRBundleManager(KRContext &context) : KRContextObject(context) {
|
||||
KRBundleManager::KRBundleManager(KRContext &context) : KRResourceManager(context) {
|
||||
|
||||
}
|
||||
|
||||
@@ -44,6 +44,21 @@ KRBundleManager::~KRBundleManager() {
|
||||
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 *pBundle = new KRBundle(*m_pContext, szName, pData);
|
||||
@@ -51,6 +66,14 @@ KRBundle *KRBundleManager::loadBundle(const char *szName, KRDataBlock *pData)
|
||||
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) {
|
||||
return m_bundles[szName];
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#ifndef KRBUNDLEMANAGER_H
|
||||
#define KRBUNDLEMANAGER_H
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
@@ -40,13 +42,17 @@
|
||||
class KRContext;
|
||||
class KRBundle;
|
||||
|
||||
class KRBundleManager : public KRContextObject {
|
||||
class KRBundleManager : public KRResourceManager {
|
||||
public:
|
||||
KRBundleManager(KRContext &context);
|
||||
~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 *getBundle(const char *szName);
|
||||
KRBundle* createBundle(const char* szName);
|
||||
|
||||
std::vector<std::string> getBundleNames();
|
||||
unordered_map<std::string, KRBundle *> getBundles();
|
||||
|
||||
2246
kraken/KRCamera.cpp
2246
kraken/KRCamera.cpp
File diff suppressed because it is too large
Load Diff
@@ -34,7 +34,7 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRShader.h"
|
||||
#include "KRPipeline.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
@@ -1,229 +1,229 @@
|
||||
//
|
||||
// KRCollider.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 "KREngine-common.h"
|
||||
#include "KRCollider.h"
|
||||
#include "KRContext.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) {
|
||||
m_model_name = model_name;
|
||||
m_layer_mask = layer_mask;
|
||||
m_audio_occlusion = audio_occlusion;
|
||||
}
|
||||
|
||||
KRCollider::~KRCollider() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRCollider::getElementName() {
|
||||
return "collider";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("layer_mask", m_layer_mask);
|
||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_model_name = e->Attribute("mesh");
|
||||
|
||||
m_layer_mask = 65535;
|
||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
||||
m_layer_mask = 65535;
|
||||
}
|
||||
|
||||
m_audio_occlusion = 1.0f;
|
||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
||||
m_audio_occlusion = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KRCollider::loadModel() {
|
||||
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
|
||||
if(m_models.size() > 0) {
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRCollider::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
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 false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
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 false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
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
|
||||
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)
|
||||
);
|
||||
|
||||
if(getBounds().intersects(sphereCastBounds)) {
|
||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
||||
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int KRCollider::getLayerMask()
|
||||
{
|
||||
return m_layer_mask;
|
||||
}
|
||||
|
||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
||||
{
|
||||
m_layer_mask = layer_mask;
|
||||
}
|
||||
|
||||
float KRCollider::getAudioOcclusion()
|
||||
{
|
||||
return m_audio_occlusion;
|
||||
}
|
||||
|
||||
void KRCollider::setAudioOcclusion(float 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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
|
||||
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);
|
||||
|
||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
GL_POP_GROUP_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRCollider.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 "KREngine-common.h"
|
||||
#include "KRCollider.h"
|
||||
#include "KRContext.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) {
|
||||
m_model_name = model_name;
|
||||
m_layer_mask = layer_mask;
|
||||
m_audio_occlusion = audio_occlusion;
|
||||
}
|
||||
|
||||
KRCollider::~KRCollider() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRCollider::getElementName() {
|
||||
return "collider";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRCollider::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("layer_mask", m_layer_mask);
|
||||
e->SetAttribute("audio_occlusion", m_audio_occlusion);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRCollider::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_model_name = e->Attribute("mesh");
|
||||
|
||||
m_layer_mask = 65535;
|
||||
if(e->QueryUnsignedAttribute("layer_mask", &m_layer_mask) != tinyxml2::XML_SUCCESS) {
|
||||
m_layer_mask = 65535;
|
||||
}
|
||||
|
||||
m_audio_occlusion = 1.0f;
|
||||
if(e->QueryFloatAttribute("audio_occlusion", &m_audio_occlusion) != tinyxml2::XML_SUCCESS) {
|
||||
m_audio_occlusion = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void KRCollider::loadModel() {
|
||||
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
|
||||
if(m_models.size() > 0) {
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRCollider::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
return AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 v1_model_space = Matrix4::Dot(getInverseModelMatrix(), v1);
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
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 false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
Vector3 v0_model_space = Matrix4::Dot(getInverseModelMatrix(), v0);
|
||||
Vector3 dir_model_space = Vector3::Normalize(Matrix4::DotNoTranslate(getInverseModelMatrix(), dir));
|
||||
HitInfo hitinfo_model_space;
|
||||
if(hitinfo.didHit()) {
|
||||
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());
|
||||
}
|
||||
|
||||
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());
|
||||
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 false;
|
||||
}
|
||||
|
||||
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
|
||||
loadModel();
|
||||
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
|
||||
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)
|
||||
);
|
||||
|
||||
if(getBounds().intersects(sphereCastBounds)) {
|
||||
if(m_models[0]->sphereCast(getModelMatrix(), v0, v1, radius, hitinfo)) {
|
||||
hitinfo = HitInfo(hitinfo.getPosition(), hitinfo.getNormal(), hitinfo.getDistance(), this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int KRCollider::getLayerMask()
|
||||
{
|
||||
return m_layer_mask;
|
||||
}
|
||||
|
||||
void KRCollider::setLayerMask(unsigned int layer_mask)
|
||||
{
|
||||
m_layer_mask = layer_mask;
|
||||
}
|
||||
|
||||
float KRCollider::getAudioOcclusion()
|
||||
{
|
||||
return m_audio_occlusion;
|
||||
}
|
||||
|
||||
void KRCollider::setAudioOcclusion(float 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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
if(m_models.size()) {
|
||||
|
||||
GL_PUSH_GROUP_MARKER("Debug Overlays");
|
||||
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
|
||||
for(int i=0; i < m_models[0]->getSubmeshCount(); i++) {
|
||||
m_models[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
|
||||
GL_POP_GROUP_MARKER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,18 @@
|
||||
#include "KRCamera.h"
|
||||
#include "KRAudioManager.h"
|
||||
#include "KRAudioSample.h"
|
||||
#include "KRBundle.h"
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include <chrono>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
int KRContext::KRENGINE_MAX_SHADER_HANDLES;
|
||||
int KRContext::KRENGINE_MAX_PIPELINE_HANDLES;
|
||||
int KRContext::KRENGINE_GPU_MEM_MAX;
|
||||
int KRContext::KRENGINE_GPU_MEM_TARGET;
|
||||
int KRContext::KRENGINE_MAX_TEXTURE_DIM;
|
||||
@@ -33,6 +39,8 @@ int KRContext::KRENGINE_SYS_PAGE_SIZE;
|
||||
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
#elif defined(ANDROID)
|
||||
|
||||
#else
|
||||
|
||||
#error Unsupported Platform
|
||||
@@ -47,8 +55,13 @@ const char *KRContext::extension_names[KRENGINE_NUM_EXTENSIONS] = {
|
||||
KRContext::log_callback *KRContext::s_log_callback = 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;
|
||||
#ifdef __APPLE__
|
||||
mach_timebase_info(&m_timebase_info);
|
||||
@@ -61,15 +74,17 @@ KRContext::KRContext() : m_streamer(*this)
|
||||
m_absolute_time = 0.0f;
|
||||
|
||||
m_pBundleManager = new KRBundleManager(*this);
|
||||
m_pShaderManager = new KRShaderManager(*this);
|
||||
m_pPipelineManager = new KRPipelineManager(*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_pSceneManager = new KRSceneManager(*this);
|
||||
m_pAnimationManager = new KRAnimationManager(*this);
|
||||
m_pAnimationCurveManager = new KRAnimationCurveManager(*this);
|
||||
m_pSoundManager = new KRAudioManager(*this);
|
||||
m_pUnknownManager = new KRUnknownManager(*this);
|
||||
m_pShaderManager = new KRShaderManager(*this);
|
||||
m_pSourceManager = new KRSourceManager(*this);
|
||||
m_streamingEnabled = true;
|
||||
|
||||
|
||||
@@ -81,7 +96,7 @@ KRContext::KRContext() : m_streamer(*this)
|
||||
KRENGINE_SYS_ALLOCATION_GRANULARITY = winSysInfo.dwAllocationGranularity;
|
||||
KRENGINE_SYS_PAGE_SIZE = winSysInfo.dwPageSize;
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
|
||||
KRENGINE_SYS_PAGE_SIZE = getpagesize();
|
||||
KRENGINE_SYS_ALLOCATION_GRANULARITY = KRENGINE_SYS_PAGE_SIZE;
|
||||
@@ -94,7 +109,6 @@ KRContext::KRContext() : m_streamer(*this)
|
||||
}
|
||||
|
||||
KRContext::~KRContext() {
|
||||
|
||||
if(m_pSceneManager) {
|
||||
delete m_pSceneManager;
|
||||
m_pSceneManager = NULL;
|
||||
@@ -115,9 +129,9 @@ KRContext::~KRContext() {
|
||||
m_pMaterialManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pShaderManager) {
|
||||
delete m_pShaderManager;
|
||||
m_pShaderManager = NULL;
|
||||
if(m_pPipelineManager) {
|
||||
delete m_pPipelineManager;
|
||||
m_pPipelineManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pAnimationManager) {
|
||||
@@ -135,6 +149,11 @@ KRContext::~KRContext() {
|
||||
m_pSoundManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pSourceManager) {
|
||||
delete m_pSourceManager;
|
||||
m_pSourceManager = NULL;
|
||||
}
|
||||
|
||||
if(m_pUnknownManager) {
|
||||
delete m_pUnknownManager;
|
||||
m_pUnknownManager = NULL;
|
||||
@@ -147,6 +166,10 @@ KRContext::~KRContext() {
|
||||
}
|
||||
|
||||
destroyDeviceContexts();
|
||||
if (m_resourceMap) {
|
||||
delete m_resourceMap;
|
||||
m_resourceMap = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void KRContext::SetLogCallback(log_callback *log_callback, void *user_data)
|
||||
@@ -187,8 +210,8 @@ KRTextureManager *KRContext::getTextureManager() {
|
||||
KRMaterialManager *KRContext::getMaterialManager() {
|
||||
return m_pMaterialManager;
|
||||
}
|
||||
KRShaderManager *KRContext::getShaderManager() {
|
||||
return m_pShaderManager;
|
||||
KRPipelineManager *KRContext::getPipelineManager() {
|
||||
return m_pPipelineManager;
|
||||
}
|
||||
KRMeshManager *KRContext::getMeshManager() {
|
||||
return m_pMeshManager;
|
||||
@@ -202,13 +225,17 @@ KRAnimationCurveManager *KRContext::getAnimationCurveManager() {
|
||||
KRAudioManager *KRContext::getAudioManager() {
|
||||
return m_pSoundManager;
|
||||
}
|
||||
KRShaderManager *KRContext::getShaderManager() {
|
||||
return m_pShaderManager;
|
||||
}
|
||||
KRSourceManager *KRContext::getSourceManager() {
|
||||
return m_pSourceManager;
|
||||
}
|
||||
KRUnknownManager *KRContext::getUnknownManager() {
|
||||
return m_pUnknownManager;
|
||||
}
|
||||
|
||||
std::vector<KRResource *> KRContext::getResources()
|
||||
{
|
||||
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
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++) {
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
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 extension = KRResource::GetFileExtension(file_name);
|
||||
|
||||
KRResource *resource = nullptr;
|
||||
|
||||
// fprintf(stderr, "KRContext::loadResource - Loading: %s\n", file_name.c_str());
|
||||
|
||||
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) {
|
||||
m_pMeshManager->loadModel(name.c_str(), data);
|
||||
resource = m_pMeshManager->loadModel(name.c_str(), data);
|
||||
} 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) {
|
||||
m_pAnimationManager->loadAnimation(name.c_str(), data);
|
||||
resource = m_pAnimationManager->loadAnimation(name.c_str(), data);
|
||||
} 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) {
|
||||
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) {
|
||||
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) {
|
||||
m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
|
||||
} else if(extension.compare("vsh") == 0) {
|
||||
m_pShaderManager->loadVertexShader(name.c_str(), data);
|
||||
} else if(extension.compare("fsh") == 0) {
|
||||
m_pShaderManager->loadFragmentShader(name.c_str(), data);
|
||||
resource = m_pTextureManager->loadTexture(name.c_str(), extension.c_str(), data);
|
||||
} else if(extension.compare("spv") == 0) {
|
||||
// SPIR-V shader binary
|
||||
resource = m_pShaderManager->load(name, extension, 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) {
|
||||
m_pMaterialManager->load(name.c_str(), data);
|
||||
resource = m_pMaterialManager->load(name.c_str(), data);
|
||||
} 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) {
|
||||
m_pSoundManager->load(name.c_str(), extension, data);
|
||||
resource = m_pSoundManager->load(name.c_str(), extension, data);
|
||||
} 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) {
|
||||
KRResource::LoadObj(*this, file_name);
|
||||
resource = KRResource::LoadObj(*this, file_name);
|
||||
#if !TARGET_OS_IPHONE
|
||||
/*
|
||||
// FINDME, TODO, HACK! - Uncomment
|
||||
} else if(extension.compare("fbx") == 0) {
|
||||
KRResource::LoadFbx(*this, file_name);
|
||||
resource = KRResource::LoadFbx(*this, file_name);
|
||||
*/
|
||||
} else if(extension.compare("blend") == 0) {
|
||||
KRResource::LoadBlenderScene(*this, file_name);
|
||||
resource = KRResource::LoadBlenderScene(*this, file_name);
|
||||
#endif
|
||||
} else {
|
||||
m_pUnknownManager->load(name, extension, data);
|
||||
resource = m_pUnknownManager->load(name, extension, data);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
void KRContext::loadResource(std::string path) {
|
||||
KRDataBlock *data = new KRDataBlock();
|
||||
if(data->load(path)) {
|
||||
loadResource(path, data);
|
||||
} else {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_ERROR, "KRContext::loadResource - Failed to open file: %s", path.c_str());
|
||||
delete data;
|
||||
KrResult KRContext::loadResource(const KrLoadResourceInfo* loadResourceInfo) {
|
||||
if (loadResourceInfo->resourceHandle < 0 || loadResourceInfo->resourceHandle >= m_resourceMapSize) {
|
||||
return KR_ERROR_OUT_OF_BOUNDS;
|
||||
}
|
||||
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() {
|
||||
@@ -343,7 +519,10 @@ float KRContext::getAbsoluteTime() const
|
||||
|
||||
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
|
||||
#else
|
||||
return (long)GetTickCount64();
|
||||
@@ -387,20 +566,20 @@ void KRContext::getMemoryStats(long &free_memory)
|
||||
|
||||
void KRContext::doStreaming()
|
||||
{
|
||||
if(m_streamingEnabled) {
|
||||
/*
|
||||
long free_memory = KRENGINE_GPU_MEM_TARGET;
|
||||
long total_memory = KRENGINE_GPU_MEM_MAX;
|
||||
*/
|
||||
/*
|
||||
if (m_streamingEnabled) {
|
||||
/*
|
||||
long free_memory = KRENGINE_GPU_MEM_TARGET;
|
||||
long total_memory = KRENGINE_GPU_MEM_MAX;
|
||||
*/
|
||||
/*
|
||||
#if TARGET_OS_IPHONE
|
||||
// FINDME, TODO, HACK! - Experimental code, need to expose through engine parameters
|
||||
const long KRENGINE_RESERVE_MEMORY = 0x4000000; // 64MB
|
||||
|
||||
|
||||
getMemoryStats(free_memory);
|
||||
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());
|
||||
|
||||
|
||||
#endif
|
||||
*/
|
||||
/*
|
||||
@@ -411,7 +590,7 @@ void KRContext::doStreaming()
|
||||
free_memory = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
// FINDME, TODO - Experimental code, need to expose through engine parameters
|
||||
const long MEMORY_WARNING_THROTTLE2_FRAMES = 30;
|
||||
@@ -421,31 +600,75 @@ void KRContext::doStreaming()
|
||||
free_memory /= 2;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
m_pMeshManager->doStreaming(total_memory, free_memory);
|
||||
m_pTextureManager->doStreaming(total_memory, free_memory);
|
||||
*/
|
||||
|
||||
|
||||
long streaming_start_frame = m_current_frame;
|
||||
|
||||
long memoryRemaining = KRENGINE_GPU_MEM_TARGET;
|
||||
long memoryRemainingThisFrame = KRENGINE_GPU_MEM_MAX - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed();
|
||||
long memoryRemainingThisFrameStart = memoryRemainingThisFrame;
|
||||
m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
|
||||
if(memoryRemainingThisFrame == memoryRemainingThisFrameStart && memoryRemainingThisFrame > 0) {
|
||||
m_last_fully_streamed_frame = streaming_start_frame;
|
||||
}
|
||||
|
||||
|
||||
|
||||
long streaming_start_frame = m_current_frame;
|
||||
|
||||
long memoryRemaining = KRENGINE_GPU_MEM_TARGET;
|
||||
long memoryRemainingThisFrame = KRENGINE_GPU_MEM_MAX - m_pTextureManager->getMemUsed() - m_pMeshManager->getMemUsed();
|
||||
long memoryRemainingThisFrameStart = memoryRemainingThisFrame;
|
||||
m_pMeshManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
m_pTextureManager->doStreaming(memoryRemaining, memoryRemainingThisFrame);
|
||||
|
||||
if (memoryRemainingThisFrame == memoryRemainingThisFrameStart && memoryRemainingThisFrame > 0) {
|
||||
m_last_fully_streamed_frame = streaming_start_frame;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,140 +1,157 @@
|
||||
//
|
||||
// KRContext.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-12.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KREngine_KRContext_h
|
||||
#define KREngine_KRContext_h
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRBundleManager.h"
|
||||
#include "KRSceneManager.h"
|
||||
#include "KRTextureManager.h"
|
||||
#include "KRMaterialManager.h"
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRMeshManager.h"
|
||||
#include "KRAnimationManager.h"
|
||||
#include "KRAnimationCurveManager.h"
|
||||
#include "KRUnknownManager.h"
|
||||
#include "KRStreamer.h"
|
||||
|
||||
class KRAudioManager;
|
||||
|
||||
class KRContext {
|
||||
public:
|
||||
static int KRENGINE_MAX_SHADER_HANDLES;
|
||||
static int KRENGINE_GPU_MEM_MAX;
|
||||
static int KRENGINE_GPU_MEM_TARGET;
|
||||
static int KRENGINE_MAX_TEXTURE_DIM;
|
||||
static int KRENGINE_MIN_TEXTURE_DIM;
|
||||
static int KRENGINE_PRESTREAM_DISTANCE;
|
||||
static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
|
||||
static int KRENGINE_SYS_PAGE_SIZE;
|
||||
|
||||
|
||||
KRContext();
|
||||
~KRContext();
|
||||
|
||||
void loadResource(const std::string &file_name, KRDataBlock *data);
|
||||
void loadResource(std::string path);
|
||||
|
||||
KRBundleManager *getBundleManager();
|
||||
KRSceneManager *getSceneManager();
|
||||
KRTextureManager *getTextureManager();
|
||||
KRMaterialManager *getMaterialManager();
|
||||
KRShaderManager *getShaderManager();
|
||||
KRMeshManager *getMeshManager();
|
||||
KRAnimationManager *getAnimationManager();
|
||||
KRAnimationCurveManager *getAnimationCurveManager();
|
||||
KRAudioManager *getAudioManager();
|
||||
KRUnknownManager *getUnknownManager();
|
||||
|
||||
KRCamera *createCamera(int width, int height);
|
||||
|
||||
enum {
|
||||
KRENGINE_GL_EXT_texture_storage,
|
||||
KRENGINE_NUM_EXTENSIONS
|
||||
};
|
||||
|
||||
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
|
||||
static bool extension_available[KRENGINE_NUM_EXTENSIONS];
|
||||
|
||||
void startFrame(float deltaTime);
|
||||
void endFrame(float deltaTime);
|
||||
|
||||
long getCurrentFrame() const;
|
||||
long getLastFullyStreamedFrame() const;
|
||||
float getAbsoluteTime() const;
|
||||
|
||||
long getAbsoluteTimeMilliseconds();
|
||||
|
||||
std::vector<KRResource *> getResources();
|
||||
bool getStreamingEnabled();
|
||||
void setStreamingEnabled(bool enable);
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_MAC
|
||||
// XXX This doesn't belong here, and might not actually be needed at all
|
||||
void getMemoryStats(long &free_memory);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LOG_LEVEL_INFORMATION,
|
||||
LOG_LEVEL_WARNING,
|
||||
LOG_LEVEL_ERROR
|
||||
} log_level;
|
||||
|
||||
typedef void log_callback(void *userdata, const std::string &message, log_level level);
|
||||
|
||||
static void SetLogCallback(log_callback *log_callback, void *user_data);
|
||||
static void Log(log_level level, const std::string message_format, ...);
|
||||
|
||||
void doStreaming();
|
||||
void receivedMemoryWarning();
|
||||
|
||||
static void activateStreamerContext();
|
||||
static void activateRenderContext();
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
static void attachToView(void *view);
|
||||
#endif
|
||||
|
||||
private:
|
||||
KRBundleManager *m_pBundleManager;
|
||||
KRSceneManager *m_pSceneManager;
|
||||
KRTextureManager *m_pTextureManager;
|
||||
KRMaterialManager *m_pMaterialManager;
|
||||
KRShaderManager *m_pShaderManager;
|
||||
KRMeshManager *m_pMeshManager;
|
||||
KRAnimationManager *m_pAnimationManager;
|
||||
KRAnimationCurveManager *m_pAnimationCurveManager;
|
||||
KRAudioManager *m_pSoundManager;
|
||||
KRUnknownManager *m_pUnknownManager;
|
||||
|
||||
void detectExtensions();
|
||||
bool m_bDetectedExtensions;
|
||||
|
||||
long m_current_frame; // TODO - Does this need to be atomic?
|
||||
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
|
||||
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
|
||||
float m_absolute_time;
|
||||
|
||||
#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;
|
||||
|
||||
static void createDeviceContexts();
|
||||
void destroyDeviceContexts();
|
||||
};
|
||||
|
||||
#endif
|
||||
//
|
||||
// KRContext.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-12.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef KREngine_KRContext_h
|
||||
#define KREngine_KRContext_h
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRBundleManager.h"
|
||||
#include "KRSceneManager.h"
|
||||
#include "KRTextureManager.h"
|
||||
#include "KRMaterialManager.h"
|
||||
#include "KRPipelineManager.h"
|
||||
#include "KRMeshManager.h"
|
||||
#include "KRAnimationManager.h"
|
||||
#include "KRAnimationCurveManager.h"
|
||||
#include "KRUnknownManager.h"
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRSourceManager.h"
|
||||
#include "KRStreamer.h"
|
||||
|
||||
class KRAudioManager;
|
||||
|
||||
class KRContext {
|
||||
public:
|
||||
static int KRENGINE_MAX_PIPELINE_HANDLES;
|
||||
static int KRENGINE_GPU_MEM_MAX;
|
||||
static int KRENGINE_GPU_MEM_TARGET;
|
||||
static int KRENGINE_MAX_TEXTURE_DIM;
|
||||
static int KRENGINE_MIN_TEXTURE_DIM;
|
||||
static int KRENGINE_PRESTREAM_DISTANCE;
|
||||
static int KRENGINE_SYS_ALLOCATION_GRANULARITY;
|
||||
static int KRENGINE_SYS_PAGE_SIZE;
|
||||
|
||||
|
||||
KRContext(const KrInitializeInfo* initializeInfo);
|
||||
~KRContext();
|
||||
|
||||
KrResult createBundle(const KrCreateBundleInfo* createBundleInfo);
|
||||
KrResult moveToBundle(const KrMoveToBundleInfo* moveToBundleInfo);
|
||||
KrResult loadResource(const KrLoadResourceInfo* loadResourceInfo);
|
||||
KrResult unloadResource(const KrUnloadResourceInfo* unloadResourceInfo);
|
||||
KrResult mapResource(const KrMapResourceInfo* mapResourceInfo);
|
||||
KrResult saveResource(const KrSaveResourceInfo* saveResourceInfo);
|
||||
|
||||
KRResource* loadResource(const std::string &file_name, KRDataBlock *data);
|
||||
|
||||
|
||||
KRBundleManager *getBundleManager();
|
||||
KRSceneManager *getSceneManager();
|
||||
KRTextureManager *getTextureManager();
|
||||
KRMaterialManager *getMaterialManager();
|
||||
KRPipelineManager *getPipelineManager();
|
||||
KRMeshManager *getMeshManager();
|
||||
KRAnimationManager *getAnimationManager();
|
||||
KRAnimationCurveManager *getAnimationCurveManager();
|
||||
KRAudioManager *getAudioManager();
|
||||
KRUnknownManager *getUnknownManager();
|
||||
KRShaderManager *getShaderManager();
|
||||
KRSourceManager *getSourceManager();
|
||||
|
||||
KRCamera *createCamera(int width, int height);
|
||||
|
||||
enum {
|
||||
KRENGINE_GL_EXT_texture_storage,
|
||||
KRENGINE_NUM_EXTENSIONS
|
||||
};
|
||||
|
||||
static const char * extension_names[KRENGINE_NUM_EXTENSIONS];
|
||||
static bool extension_available[KRENGINE_NUM_EXTENSIONS];
|
||||
|
||||
void startFrame(float deltaTime);
|
||||
void endFrame(float deltaTime);
|
||||
|
||||
long getCurrentFrame() const;
|
||||
long getLastFullyStreamedFrame() const;
|
||||
float getAbsoluteTime() const;
|
||||
|
||||
long getAbsoluteTimeMilliseconds();
|
||||
|
||||
std::vector<KRResource *> getResources();
|
||||
bool getStreamingEnabled();
|
||||
void setStreamingEnabled(bool enable);
|
||||
|
||||
#if TARGET_OS_IPHONE || TARGET_OS_MAC
|
||||
// XXX This doesn't belong here, and might not actually be needed at all
|
||||
void getMemoryStats(long &free_memory);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LOG_LEVEL_INFORMATION,
|
||||
LOG_LEVEL_WARNING,
|
||||
LOG_LEVEL_ERROR
|
||||
} log_level;
|
||||
|
||||
typedef void log_callback(void *userdata, const std::string &message, log_level level);
|
||||
|
||||
static void SetLogCallback(log_callback *log_callback, void *user_data);
|
||||
static void Log(log_level level, const std::string message_format, ...);
|
||||
|
||||
void doStreaming();
|
||||
void receivedMemoryWarning();
|
||||
|
||||
static void activateStreamerContext();
|
||||
static void activateRenderContext();
|
||||
|
||||
#if TARGET_OS_MAC
|
||||
static void attachToView(void *view);
|
||||
#endif
|
||||
|
||||
private:
|
||||
KRBundleManager *m_pBundleManager;
|
||||
KRSceneManager *m_pSceneManager;
|
||||
KRTextureManager *m_pTextureManager;
|
||||
KRMaterialManager *m_pMaterialManager;
|
||||
KRPipelineManager *m_pPipelineManager;
|
||||
KRMeshManager *m_pMeshManager;
|
||||
KRAnimationManager *m_pAnimationManager;
|
||||
KRAnimationCurveManager *m_pAnimationCurveManager;
|
||||
KRAudioManager *m_pSoundManager;
|
||||
KRUnknownManager *m_pUnknownManager;
|
||||
KRShaderManager *m_pShaderManager;
|
||||
KRSourceManager *m_pSourceManager;
|
||||
|
||||
KRResource** m_resourceMap;
|
||||
size_t m_resourceMapSize;
|
||||
|
||||
void detectExtensions();
|
||||
bool m_bDetectedExtensions;
|
||||
|
||||
long m_current_frame; // TODO - Does this need to be atomic?
|
||||
long m_last_memory_warning_frame; // TODO - Does this need to be atomic?
|
||||
long m_last_fully_streamed_frame; // TODO - Does this need to be atomic?
|
||||
float m_absolute_time;
|
||||
|
||||
#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
|
||||
|
||||
@@ -20,7 +20,7 @@ void KRContext::destroyDeviceContexts()
|
||||
gRenderContext = nil;
|
||||
}
|
||||
|
||||
void KRContext::createDeviceContexts()
|
||||
void createGLDeviceContexts()
|
||||
{
|
||||
if(gRenderContext == nil) {
|
||||
|
||||
@@ -63,20 +63,20 @@ void KRContext::createDeviceContexts()
|
||||
|
||||
void KRContext::activateStreamerContext()
|
||||
{
|
||||
createDeviceContexts();
|
||||
createGLDeviceContexts();
|
||||
[gStreamerContext makeCurrentContext];
|
||||
}
|
||||
|
||||
void KRContext::activateRenderContext()
|
||||
{
|
||||
createDeviceContexts();
|
||||
createGLDeviceContexts();
|
||||
[gRenderContext update];
|
||||
[gRenderContext makeCurrentContext];
|
||||
}
|
||||
|
||||
void KRContext::attachToView(void *view)
|
||||
{
|
||||
createDeviceContexts();
|
||||
createGLDeviceContexts();
|
||||
NSView *v = (NSView *)view;
|
||||
[gRenderContext setView: v];
|
||||
[gRenderContext update];
|
||||
|
||||
@@ -1,207 +1,207 @@
|
||||
//
|
||||
// KREngine.h
|
||||
// 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 "KRDSP.h"
|
||||
|
||||
#ifdef KRDSP_SLOW
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
namespace KRDSP {
|
||||
|
||||
FFTWorkspace::FFTWorkspace()
|
||||
{
|
||||
sin_table = nullptr;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
|
||||
FFTWorkspace::~FFTWorkspace()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void FFTWorkspace::create(size_t length)
|
||||
{
|
||||
size_t size = (length / 2);
|
||||
cos_table = new float[size];
|
||||
sin_table = new float[size];
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
float a = 2.0f * M_PI * i / length;
|
||||
cos_table[i] = cos(a);
|
||||
sin_table[i] = sin(a);
|
||||
}
|
||||
}
|
||||
|
||||
void FFTWorkspace::destroy()
|
||||
{
|
||||
if (sin_table) {
|
||||
delete sin_table;
|
||||
sin_table = nullptr;
|
||||
}
|
||||
if (cos_table) {
|
||||
delete cos_table;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
// Radix-2 Decimation in Time FFT Algorithm
|
||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
||||
|
||||
// Only power-of-two sizes supported
|
||||
assert((count & (count - 1)) == 0);
|
||||
|
||||
int levels = 0;
|
||||
while (1 << levels <= count) {
|
||||
levels++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t j = 0;
|
||||
for (int k = 0; k < levels; k++) {
|
||||
j <<= 1;
|
||||
j |= ((i >> k) & 1);
|
||||
}
|
||||
if (j > i) {
|
||||
float temp = src->realp[i];
|
||||
src->realp[i] = src->realp[j];
|
||||
src->realp[j] = temp;
|
||||
temp = src->imagp[i];
|
||||
src->imagp[i] = src->imagp[j];
|
||||
src->imagp[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t size = 2; size <= count; size *= 2) {
|
||||
size_t halfsize = size / 2;
|
||||
size_t step = count / size;
|
||||
for (size_t i = 0; i < count; i += size) {
|
||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
||||
temp_real += src->imagp[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];
|
||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
||||
src->realp[j] += temp_real;
|
||||
src->imagp[j] += temp_imag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
SplitComplex swapped;
|
||||
swapped.imagp = src->realp;
|
||||
swapped.realp = src->imagp;
|
||||
FFTForward(workspace, &swapped, count);
|
||||
}
|
||||
|
||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
||||
{
|
||||
const short *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + destStride * count) {
|
||||
*w = (float)*r;
|
||||
r += srcStride;
|
||||
w += destStride;
|
||||
}
|
||||
}
|
||||
|
||||
void Scale(float *buffer, float scale, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
while (w < buffer + count) {
|
||||
*w *= scale;
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
||||
{
|
||||
const float *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + count) {
|
||||
*w = *r * scale;
|
||||
w++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
||||
{
|
||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
||||
}
|
||||
|
||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
float s = scaleStart;
|
||||
while (w < buffer + count) {
|
||||
*w *= s;
|
||||
w++;
|
||||
s += scaleStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
const float *r = buffer2;
|
||||
while (w < buffer + bufferStride * count) {
|
||||
*w *= *r;
|
||||
w += bufferStride;
|
||||
r += buffer2Stride;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
buffer->imagp[i] += buffer2->imagp[i];
|
||||
buffer->realp[i] += buffer2->realp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; 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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KRDSP
|
||||
|
||||
#endif // KRDSP_SLOW
|
||||
//
|
||||
// KREngine.h
|
||||
// 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 "KRDSP.h"
|
||||
|
||||
#ifdef KRDSP_SLOW
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
namespace KRDSP {
|
||||
|
||||
FFTWorkspace::FFTWorkspace()
|
||||
{
|
||||
sin_table = nullptr;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
|
||||
FFTWorkspace::~FFTWorkspace()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void FFTWorkspace::create(size_t length)
|
||||
{
|
||||
size_t size = (length / 2);
|
||||
cos_table = new float[size];
|
||||
sin_table = new float[size];
|
||||
for (int i = 0; i < size / 2; i++) {
|
||||
float a = 2.0f * (float)M_PI * i / length;
|
||||
cos_table[i] = cos(a);
|
||||
sin_table[i] = sin(a);
|
||||
}
|
||||
}
|
||||
|
||||
void FFTWorkspace::destroy()
|
||||
{
|
||||
if (sin_table) {
|
||||
delete sin_table;
|
||||
sin_table = nullptr;
|
||||
}
|
||||
if (cos_table) {
|
||||
delete cos_table;
|
||||
cos_table = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void FFTForward(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
// Radix-2 Decimation in Time FFT Algorithm
|
||||
// http://en.dsplib.org/content/fft_dec_in_time.html
|
||||
|
||||
// Only power-of-two sizes supported
|
||||
assert((count & (count - 1)) == 0);
|
||||
|
||||
unsigned int levels = 0;
|
||||
while (1 << levels <= (int)count) {
|
||||
levels++;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
size_t j = 0;
|
||||
for (int k = 0; k < (int)levels; k++) {
|
||||
j <<= 1;
|
||||
j |= ((i >> k) & 1);
|
||||
}
|
||||
if (j > i) {
|
||||
float temp = src->realp[i];
|
||||
src->realp[i] = src->realp[j];
|
||||
src->realp[j] = temp;
|
||||
temp = src->imagp[i];
|
||||
src->imagp[i] = src->imagp[j];
|
||||
src->imagp[j] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t size = 2; size <= count; size *= 2) {
|
||||
size_t halfsize = size / 2;
|
||||
size_t step = count / size;
|
||||
for (size_t i = 0; i < count; i += size) {
|
||||
for (size_t j = i, k = 0; j < i + halfsize; j++, k += step) {
|
||||
float temp_real = src->realp[j + halfsize] * workspace.cos_table[k];
|
||||
temp_real += src->imagp[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];
|
||||
src->realp[j + halfsize] = src->realp[j] - temp_real;
|
||||
src->imagp[j + halfsize] = src->imagp[j] - temp_imag;
|
||||
src->realp[j] += temp_real;
|
||||
src->imagp[j] += temp_imag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FFTInverse(const FFTWorkspace &workspace, SplitComplex *src, size_t count)
|
||||
{
|
||||
SplitComplex swapped;
|
||||
swapped.imagp = src->realp;
|
||||
swapped.realp = src->imagp;
|
||||
FFTForward(workspace, &swapped, count);
|
||||
}
|
||||
|
||||
void Int16ToFloat(const short *src, size_t srcStride, float *dest, size_t destStride, size_t count)
|
||||
{
|
||||
const short *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + destStride * count) {
|
||||
*w = (float)*r;
|
||||
r += srcStride;
|
||||
w += destStride;
|
||||
}
|
||||
}
|
||||
|
||||
void Scale(float *buffer, float scale, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
while (w < buffer + count) {
|
||||
*w *= scale;
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const float *src, float scale, float *dest, size_t count)
|
||||
{
|
||||
const float *r = src;
|
||||
float *w = dest;
|
||||
while (w < dest + count) {
|
||||
*w = *r * scale;
|
||||
w++;
|
||||
r++;
|
||||
}
|
||||
}
|
||||
|
||||
void ScaleCopy(const SplitComplex *src, float scale, SplitComplex *dest, size_t count)
|
||||
{
|
||||
ScaleCopy(src->realp, scale, dest->realp, count);
|
||||
ScaleCopy(src->imagp, scale, dest->imagp, count);
|
||||
}
|
||||
|
||||
void ScaleRamp(float *buffer, float scaleStart, float scaleStep, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
float s = scaleStart;
|
||||
while (w < buffer + count) {
|
||||
*w *= s;
|
||||
w++;
|
||||
s += scaleStep;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(float *buffer, size_t bufferStride, const float *buffer2, size_t buffer2Stride, size_t count)
|
||||
{
|
||||
float *w = buffer;
|
||||
const float *r = buffer2;
|
||||
while (w < buffer + bufferStride * count) {
|
||||
*w *= *r;
|
||||
w += bufferStride;
|
||||
r += buffer2Stride;
|
||||
}
|
||||
}
|
||||
|
||||
void Accumulate(SplitComplex *buffer, const SplitComplex *buffer2, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
buffer->imagp[i] += buffer2->imagp[i];
|
||||
buffer->realp[i] += buffer2->realp[i];
|
||||
}
|
||||
}
|
||||
|
||||
void Multiply(const SplitComplex *a, const SplitComplex *b, SplitComplex *c, size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; 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];
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KRDSP
|
||||
|
||||
#endif // KRDSP_SLOW
|
||||
|
||||
@@ -35,6 +35,10 @@
|
||||
#include "KRContext.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_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 (m_hPackFile != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(m_hPackFile);
|
||||
// Memory mapped file
|
||||
if (m_fileOwnerDataBlock == this) {
|
||||
CloseHandle(m_hPackFile);
|
||||
}
|
||||
m_hPackFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
@@ -136,7 +143,6 @@ bool KRDataBlock::load(const std::string &path)
|
||||
bool success = false;
|
||||
unload();
|
||||
|
||||
struct stat statbuf;
|
||||
m_bReadOnly = true;
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
@@ -146,7 +152,7 @@ bool KRDataBlock::load(const std::string &path)
|
||||
m_fileName = KRResource::GetFileBase(path);
|
||||
FILE_STANDARD_INFO 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;
|
||||
success = true;
|
||||
}
|
||||
@@ -156,6 +162,7 @@ bool KRDataBlock::load(const std::string &path)
|
||||
if(m_fdPackFile >= 0) {
|
||||
m_fileOwnerDataBlock = this;
|
||||
m_fileName = KRResource::GetFileBase(path);
|
||||
struct stat statbuf;
|
||||
if(fstat(m_fdPackFile, &statbuf) >= 0) {
|
||||
m_data_size = statbuf.st_size;
|
||||
m_data_offset = 0;
|
||||
@@ -177,9 +184,9 @@ KRDataBlock *KRDataBlock::getSubBlock(int start, int length)
|
||||
|
||||
new_block->m_data_size = length;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if(m_hPackFile) {
|
||||
if(m_hPackFile != INVALID_HANDLE_VALUE) {
|
||||
new_block->m_hPackFile = m_hPackFile;
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
if (m_fdPackFile) {
|
||||
new_block->m_fdPackFile = m_fdPackFile;
|
||||
#else
|
||||
@@ -216,8 +223,8 @@ size_t KRDataBlock::getSize() const {
|
||||
void KRDataBlock::expand(size_t size)
|
||||
{
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if(m_data == NULL && m_hPackFile == 0) {
|
||||
#elif defined(__APPLE__)
|
||||
if(m_data == NULL && m_hPackFile == INVALID_HANDLE_VALUE) {
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
if (m_data == NULL && m_fdPackFile == 0) {
|
||||
#else
|
||||
#error Unsupported
|
||||
@@ -265,13 +272,13 @@ void KRDataBlock::append(void *data, size_t size) {
|
||||
|
||||
// Copy the entire data block to the destination pointer
|
||||
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
|
||||
void KRDataBlock::copy(void *dest, int start, int count) {
|
||||
#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
|
||||
|
||||
LARGE_INTEGER distance;
|
||||
@@ -290,7 +297,7 @@ void KRDataBlock::copy(void *dest, int start, int count) {
|
||||
bytes_remaining -= bytes_read;
|
||||
}
|
||||
assert(bytes_remaining == 0);
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
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
|
||||
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;
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
int fdNewFile = open(path.c_str(), O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
|
||||
if(fdNewFile == -1) {
|
||||
return false;
|
||||
@@ -410,6 +417,36 @@ std::string KRDataBlock::getString()
|
||||
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
|
||||
void KRDataBlock::lock()
|
||||
{
|
||||
@@ -417,8 +454,8 @@ void KRDataBlock::lock()
|
||||
|
||||
// Memory mapped file; ensure data is mapped to ram
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if(m_hFileMapping) {
|
||||
#elif defined(__APPLE__)
|
||||
if(m_hPackFile != INVALID_HANDLE_VALUE) {
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
if(m_fdPackFile) {
|
||||
#else
|
||||
#error Unsupported
|
||||
@@ -432,11 +469,17 @@ void KRDataBlock::lock()
|
||||
assert(m_mmapData == NULL);
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
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);
|
||||
|
||||
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);
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
//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
|
||||
|
||||
@@ -495,8 +538,8 @@ void KRDataBlock::unlock()
|
||||
|
||||
// Memory mapped file; ensure data is unmapped from ram
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (m_hPackFile) {
|
||||
#elif defined(__APPLE__)
|
||||
if (m_hPackFile != INVALID_HANDLE_VALUE) {
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
if(m_fdPackFile) {
|
||||
#else
|
||||
#error Undefined
|
||||
@@ -514,7 +557,7 @@ void KRDataBlock::unlock()
|
||||
CloseHandle(m_hFileMapping);
|
||||
m_hFileMapping = NULL;
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
munmap(m_mmapData, m_data_size);
|
||||
#else
|
||||
#error Undefined
|
||||
|
||||
@@ -106,7 +106,7 @@ private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_hPackFile;
|
||||
HANDLE m_hFileMapping;
|
||||
#elif defined(__APPLE__)
|
||||
#elif defined(__APPLE__) || defined(ANDROID)
|
||||
int m_fdPackFile;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,135 +1,135 @@
|
||||
//
|
||||
// KRDirectionalLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRContext.h"
|
||||
#include "assert.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRDirectionalLight::~KRDirectionalLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRDirectionalLight::getElementName() {
|
||||
return "directional_light";
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
int cShadows = 1;
|
||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||
/*
|
||||
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 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 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()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
||||
|
||||
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
|
||||
|
||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// Matrix4 matShadowProjection = Matrix4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
Matrix4 matShadowProjection = Matrix4();
|
||||
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.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
|
||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||
|
||||
Matrix4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
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 minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||
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
|
||||
m_shadowViewports[iShadow] = newShadowViewport;
|
||||
shadowValid[iShadow] = false;
|
||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRDirectionalLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||
matModelViewInverseTranspose.transpose();
|
||||
matModelViewInverseTranspose.invert();
|
||||
|
||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
||||
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);
|
||||
if(getContext().getShaderManager()->selectShader(*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(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRDirectionalLight::getBounds()
|
||||
{
|
||||
return AABB::Infinite();
|
||||
}
|
||||
//
|
||||
// KRDirectionalLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRPipeline.h"
|
||||
#include "KRContext.h"
|
||||
#include "assert.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRDirectionalLight::KRDirectionalLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRDirectionalLight::~KRDirectionalLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRDirectionalLight::getElementName() {
|
||||
return "directional_light";
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getWorldLightDirection() {
|
||||
return Matrix4::Dot(getWorldRotation().rotationMatrix(), getLocalLightDirection());
|
||||
}
|
||||
|
||||
Vector3 KRDirectionalLight::getLocalLightDirection() {
|
||||
return Vector3::Up(); //&KRF HACK changed from Vector3::Forward(); - to compensate for the way Maya handles post rotation.
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
int cShadows = 1;
|
||||
for(int iShadow=0; iShadow < cShadows; iShadow++) {
|
||||
/*
|
||||
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 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 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()));
|
||||
worldSpacefrustrumSliceBounds.scale(KRENGINE_SHADOW_BOUNDS_EXTRA_SCALE);
|
||||
|
||||
Vector3 shadowLook = -Vector3::Normalize(getWorldLightDirection());
|
||||
|
||||
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
|
||||
|
||||
// Matrix4 matShadowView = Matrix4::LookAt(viewport.getCameraPosition() - shadowLook, viewport.getCameraPosition(), shadowUp);
|
||||
// Matrix4 matShadowProjection = Matrix4();
|
||||
// matShadowProjection.scale(0.001, 0.001, 0.001);
|
||||
|
||||
Matrix4 matShadowView = Matrix4::LookAt(worldSpacefrustrumSliceBounds.center() - shadowLook, worldSpacefrustrumSliceBounds.center(), shadowUp);
|
||||
Matrix4 matShadowProjection = Matrix4();
|
||||
AABB shadowSpaceFrustrumSliceBounds = AABB::Create(worldSpacefrustrumSliceBounds.min, worldSpacefrustrumSliceBounds.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
|
||||
matShadowProjection.scale(1.0f / shadowSpaceFrustrumSliceBounds.size().x, 1.0f / shadowSpaceFrustrumSliceBounds.size().y, 1.0f / shadowSpaceFrustrumSliceBounds.size().z);
|
||||
|
||||
Matrix4 matBias;
|
||||
matBias.bias();
|
||||
matShadowProjection *= matBias;
|
||||
|
||||
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 minimumShadowBounds = AABB::Create(-Vector3::One(), Vector3::One(), Matrix4::Invert(newShadowViewport.getViewProjectionMatrix()));
|
||||
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
|
||||
m_shadowViewports[iShadow] = newShadowViewport;
|
||||
shadowValid[iShadow] = false;
|
||||
fprintf(stderr, "Kraken - Generate shadow maps...\n");
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRDirectionalLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Matrix4 matModelViewInverseTranspose = viewport.getViewMatrix() * getModelMatrix();
|
||||
matModelViewInverseTranspose.transpose();
|
||||
matModelViewInverseTranspose.invert();
|
||||
|
||||
Vector3 light_direction_view_space = getWorldLightDirection();
|
||||
light_direction_view_space = Matrix4::Dot(matModelViewInverseTranspose, light_direction_view_space);
|
||||
light_direction_view_space.normalize();
|
||||
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), std::vector<KRPointLight *>(), this_light, std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_DIRECTION_VIEW_SPACE, light_direction_view_space);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AABB KRDirectionalLight::getBounds()
|
||||
{
|
||||
return AABB::Infinite();
|
||||
}
|
||||
|
||||
@@ -47,10 +47,6 @@ using namespace kraken;
|
||||
|
||||
#endif
|
||||
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/signals2/mutex.hpp>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
@@ -103,7 +99,20 @@ using std::unordered_map;
|
||||
using std::unordered_multimap;
|
||||
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 <cstdint>
|
||||
|
||||
@@ -732,7 +732,7 @@ void kraken::set_debug_text(const std::string &print_text)
|
||||
-(void) setSunTemperature:(float)t
|
||||
{
|
||||
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 - 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
|
||||
{
|
||||
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 - 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
|
||||
{
|
||||
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 - 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
|
||||
{
|
||||
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 - t) * 2.0f) * i,
|
||||
(t < 0.5f ? 1.0f : (1.0f - t) * 2.0f) * i
|
||||
|
||||
@@ -4,10 +4,14 @@
|
||||
#include "vector2.h"
|
||||
#include "vector3.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>
|
||||
#elif defined(__linux__) || defined(__unix__) || defined(__posix__)
|
||||
#elif (defined(__linux__) || defined(__unix__) || defined(__posix__))
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glext.h>
|
||||
|
||||
@@ -1,173 +1,173 @@
|
||||
//
|
||||
// KRLODGroup.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRLODGroup.h"
|
||||
#include "KRLODSet.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_min_distance = 0.0f;
|
||||
m_max_distance = 0.0f;
|
||||
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
|
||||
m_use_world_units = true;
|
||||
}
|
||||
|
||||
KRLODGroup::~KRLODGroup()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRLODGroup::getElementName() {
|
||||
return "lod_group";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("min_distance", m_min_distance);
|
||||
e->SetAttribute("max_distance", m_max_distance);
|
||||
|
||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||
|
||||
|
||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||
|
||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_min_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_min_distance = 0.0f;
|
||||
}
|
||||
|
||||
m_max_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_max_distance = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
float x=0.0f, y=0.0f, z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
m_reference.min = Vector3::Create(x,y,z);
|
||||
|
||||
x=0.0f; y=0.0f; z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
m_reference.max = Vector3::Create(x,y,z);
|
||||
|
||||
m_use_world_units = true;
|
||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||
m_use_world_units = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AABB &KRLODGroup::getReference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
void KRLODGroup::setReference(const AABB &reference)
|
||||
{
|
||||
m_reference = reference;
|
||||
}
|
||||
|
||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
||||
{
|
||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else {
|
||||
float lod_bias = viewport.getLODBias();
|
||||
lod_bias = pow(2.0f, -lod_bias);
|
||||
|
||||
// Compare using squared distances as sqrt is expensive
|
||||
float sqr_distance;
|
||||
float sqr_prestream_distance;
|
||||
|
||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||
|
||||
if(m_use_world_units) {
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
sqr_prestream_distance = getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE;
|
||||
} else {
|
||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
|
||||
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?
|
||||
|
||||
}
|
||||
|
||||
float sqr_min_visible_distance = m_min_distance * m_min_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)) {
|
||||
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)) {
|
||||
return LOD_VISIBILITY_PRESTREAM;
|
||||
} else {
|
||||
return LOD_VISIBILITY_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRLODGroup::getMinDistance()
|
||||
{
|
||||
return m_min_distance;
|
||||
}
|
||||
|
||||
float KRLODGroup::getMaxDistance()
|
||||
{
|
||||
return m_max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMinDistance(float min_distance)
|
||||
{
|
||||
m_min_distance = min_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMaxDistance(float max_distance)
|
||||
{
|
||||
m_max_distance = max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||
{
|
||||
m_use_world_units = use_world_units;
|
||||
}
|
||||
|
||||
bool KRLODGroup::getUseWorldUnits() const
|
||||
{
|
||||
return m_use_world_units;
|
||||
}
|
||||
//
|
||||
// KRLODGroup.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRLODGroup.h"
|
||||
#include "KRLODSet.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRLODGroup::KRLODGroup(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_min_distance = 0.0f;
|
||||
m_max_distance = 0.0f;
|
||||
m_reference = AABB::Create(Vector3::Zero(), Vector3::Zero());
|
||||
m_use_world_units = true;
|
||||
}
|
||||
|
||||
KRLODGroup::~KRLODGroup()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRLODGroup::getElementName() {
|
||||
return "lod_group";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLODGroup::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("min_distance", m_min_distance);
|
||||
e->SetAttribute("max_distance", m_max_distance);
|
||||
|
||||
e->SetAttribute("reference_min_x", m_reference.min.x);
|
||||
e->SetAttribute("reference_min_y", m_reference.min.y);
|
||||
e->SetAttribute("reference_min_z", m_reference.min.z);
|
||||
|
||||
|
||||
e->SetAttribute("reference_max_x", m_reference.max.x);
|
||||
e->SetAttribute("reference_max_y", m_reference.max.y);
|
||||
e->SetAttribute("reference_max_z", m_reference.max.z);
|
||||
|
||||
e->SetAttribute("use_world_units", m_use_world_units ? "true" : "false");
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLODGroup::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_min_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("min_distance", &m_min_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_min_distance = 0.0f;
|
||||
}
|
||||
|
||||
m_max_distance = 0.0f;
|
||||
if(e->QueryFloatAttribute("max_distance", &m_max_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_max_distance = 0.0f;
|
||||
}
|
||||
|
||||
|
||||
float x=0.0f, y=0.0f, z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_min_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_min_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
|
||||
m_reference.min = Vector3::Create(x,y,z);
|
||||
|
||||
x=0.0f; y=0.0f; z=0.0f;
|
||||
if(e->QueryFloatAttribute("reference_max_x", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_y", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 0.0f;
|
||||
}
|
||||
if(e->QueryFloatAttribute("reference_max_z", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 0.0f;
|
||||
}
|
||||
m_reference.max = Vector3::Create(x,y,z);
|
||||
|
||||
m_use_world_units = true;
|
||||
if(e->QueryBoolAttribute("use_world_units", &m_use_world_units) != tinyxml2::XML_SUCCESS) {
|
||||
m_use_world_units = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AABB &KRLODGroup::getReference() const
|
||||
{
|
||||
return m_reference;
|
||||
}
|
||||
|
||||
void KRLODGroup::setReference(const AABB &reference)
|
||||
{
|
||||
m_reference = reference;
|
||||
}
|
||||
|
||||
KRNode::LodVisibility KRLODGroup::calcLODVisibility(const KRViewport &viewport)
|
||||
{
|
||||
if(m_min_distance == 0 && m_max_distance == 0) {
|
||||
return LOD_VISIBILITY_VISIBLE;
|
||||
} else {
|
||||
float lod_bias = viewport.getLODBias();
|
||||
lod_bias = pow(2.0f, -lod_bias);
|
||||
|
||||
// Compare using squared distances as sqrt is expensive
|
||||
float sqr_distance;
|
||||
float sqr_prestream_distance;
|
||||
|
||||
Vector3 world_camera_position = viewport.getCameraPosition();
|
||||
Vector3 local_camera_position = worldToLocal(world_camera_position);
|
||||
Vector3 local_reference_point = m_reference.nearestPoint(local_camera_position);
|
||||
|
||||
if(m_use_world_units) {
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
sqr_distance = (world_camera_position - world_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
sqr_prestream_distance = (float)(getContext().KRENGINE_PRESTREAM_DISTANCE * getContext().KRENGINE_PRESTREAM_DISTANCE);
|
||||
} else {
|
||||
sqr_distance = (local_camera_position - local_reference_point).sqrMagnitude() * (lod_bias * lod_bias);
|
||||
|
||||
Vector3 world_reference_point = localToWorld(local_reference_point);
|
||||
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_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)) {
|
||||
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)) {
|
||||
return LOD_VISIBILITY_PRESTREAM;
|
||||
} else {
|
||||
return LOD_VISIBILITY_HIDDEN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float KRLODGroup::getMinDistance()
|
||||
{
|
||||
return m_min_distance;
|
||||
}
|
||||
|
||||
float KRLODGroup::getMaxDistance()
|
||||
{
|
||||
return m_max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMinDistance(float min_distance)
|
||||
{
|
||||
m_min_distance = min_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setMaxDistance(float max_distance)
|
||||
{
|
||||
m_max_distance = max_distance;
|
||||
}
|
||||
|
||||
void KRLODGroup::setUseWorldUnits(bool use_world_units)
|
||||
{
|
||||
m_use_world_units = use_world_units;
|
||||
}
|
||||
|
||||
bool KRLODGroup::getUseWorldUnits() const
|
||||
{
|
||||
return m_use_world_units;
|
||||
}
|
||||
|
||||
@@ -1,485 +1,485 @@
|
||||
//
|
||||
// KRLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRLight.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_intensity = 1.0f;
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
m_color = Vector3::One();
|
||||
m_flareTexture = "";
|
||||
m_pFlareTexture = NULL;
|
||||
m_flareSize = 0.0f;
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
m_casts_shadow = true;
|
||||
m_light_shafts = true;
|
||||
m_dust_particle_density = 0.1f;
|
||||
m_dust_particle_size = 1.0f;
|
||||
m_occlusionQuery = 0;
|
||||
|
||||
// Initialize shadow buffers
|
||||
m_cShadowBuffers = 0;
|
||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
||||
shadowFramebuffer[iBuffer] = 0;
|
||||
shadowDepthTexture[iBuffer] = 0;
|
||||
shadowValid[iBuffer] = false;
|
||||
}
|
||||
}
|
||||
|
||||
KRLight::~KRLight()
|
||||
{
|
||||
if(m_occlusionQuery) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
m_occlusionQuery = 0;
|
||||
}
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("intensity", m_intensity);
|
||||
e->SetAttribute("color_r", m_color.x);
|
||||
e->SetAttribute("color_g", m_color.y);
|
||||
e->SetAttribute("color_b", m_color.z);
|
||||
e->SetAttribute("decay_start", m_decayStart);
|
||||
e->SetAttribute("flare_size", m_flareSize);
|
||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
float x=1.0f,y=1.0f,z=1.0f;
|
||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 1.0;
|
||||
}
|
||||
m_color = Vector3::Create(x,y,z);
|
||||
|
||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_intensity = 100.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
||||
m_decayStart = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareSize = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
||||
m_casts_shadow = true;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
||||
m_light_shafts = true;
|
||||
}
|
||||
|
||||
m_dust_particle_density = 0.1f;
|
||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_density = 0.1f;
|
||||
}
|
||||
|
||||
m_dust_particle_size = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_size = 1.0f;
|
||||
}
|
||||
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
}
|
||||
|
||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
||||
if(szFlareTexture) {
|
||||
m_flareTexture = szFlareTexture;
|
||||
} else {
|
||||
m_flareTexture = "";
|
||||
}
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
||||
m_flareTexture = flare_texture;
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareSize(float flare_size) {
|
||||
m_flareSize = flare_size;
|
||||
}
|
||||
|
||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
||||
m_flareOcclusionSize = occlusion_size;
|
||||
}
|
||||
|
||||
void KRLight::setIntensity(float intensity) {
|
||||
m_intensity = intensity;
|
||||
}
|
||||
float KRLight::getIntensity() {
|
||||
return m_intensity;
|
||||
}
|
||||
|
||||
const Vector3 &KRLight::getColor() {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void KRLight::setColor(const Vector3 &color) {
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
void KRLight::setDecayStart(float decayStart) {
|
||||
m_decayStart = decayStart;
|
||||
}
|
||||
|
||||
float KRLight::getDecayStart() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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))) {
|
||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
||||
renderShadowBuffers(pCamera);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
||||
// 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(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
||||
|
||||
float particle_range = 600.0f;
|
||||
|
||||
int particle_count = m_dust_particle_density * pow(particle_range, 3);
|
||||
if(particle_count > KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES) particle_count = KRMeshManager::KRENGINE_MAX_RANDOM_PARTICLES;
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
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.translate(viewport.getCameraPosition());
|
||||
|
||||
std::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(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);
|
||||
|
||||
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())) {
|
||||
|
||||
pParticleShader->setUniform(KRShader::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(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(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);
|
||||
|
||||
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())) {
|
||||
int slice_count = (int)(pCamera->settings.volumetric_environment_quality * 495.0) + 5;
|
||||
|
||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
||||
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(KRShader::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
||||
|
||||
KRDataBlock index_data;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
|
||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
||||
if(m_parentNode) {
|
||||
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())) {
|
||||
|
||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||
#if TARGET_OS_IPHONE
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
if(m_occlusionQuery) {
|
||||
GLuint params = 0;
|
||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
|
||||
if(params) {
|
||||
|
||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
||||
}
|
||||
|
||||
if(m_pFlareTexture) {
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
|
||||
if(getContext().getShaderManager()->selectShader(*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(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, m_flareSize);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
||||
// First deallocate buffers no longer needed
|
||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
||||
if (shadowDepthTexture[iShadow]) {
|
||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
||||
shadowDepthTexture[iShadow] = 0;
|
||||
}
|
||||
|
||||
if (shadowFramebuffer[iShadow]) {
|
||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
shadowFramebuffer[iShadow] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate newly required buffers
|
||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
||||
|
||||
if(!shadowDepthTexture[iShadow]) {
|
||||
shadowValid[iShadow] = false;
|
||||
|
||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
||||
// ===== Create offscreen shadow framebuffer object =====
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
|
||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
||||
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_MAG_FILTER, GL_NEAREST));
|
||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
#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_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
||||
#endif
|
||||
GLDEBUG(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, viewportSize.x, viewportSize.y, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
|
||||
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||
}
|
||||
}
|
||||
|
||||
m_cShadowBuffers = cBuffers;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
void KRLight::invalidateShadowBuffers()
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
shadowValid[iShadow] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
if(!shadowValid[iShadow]) {
|
||||
shadowValid[iShadow] = true;
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
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(glClearDepthf(0.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glViewport(1, 1, m_shadowViewports[iShadow].getSize().x - 2, m_shadowViewports[iShadow].getSize().y - 2));
|
||||
|
||||
GLDEBUG(glClearDepthf(1.0f));
|
||||
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glDisable(GL_DITHER));
|
||||
|
||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LESS));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
|
||||
// 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);
|
||||
|
||||
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());
|
||||
|
||||
|
||||
getScene().render(pCamera, m_shadowViewports[iShadow].getVisibleBounds(), m_shadowViewports[iShadow], KRNode::RENDER_PASS_SHADOWMAP, true);
|
||||
|
||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int KRLight::getShadowBufferCount()
|
||||
{
|
||||
int cBuffers=0;
|
||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||
if(shadowValid[iBuffer]) {
|
||||
cBuffers++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cBuffers;
|
||||
}
|
||||
|
||||
GLuint *KRLight::getShadowTextures()
|
||||
{
|
||||
return shadowDepthTexture;
|
||||
}
|
||||
|
||||
KRViewport *KRLight::getShadowViewports()
|
||||
{
|
||||
return m_shadowViewports;
|
||||
}
|
||||
//
|
||||
// KRLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRLight.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRPipelineManager.h"
|
||||
#include "KRPipeline.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRLight::KRLight(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_intensity = 1.0f;
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
m_color = Vector3::One();
|
||||
m_flareTexture = "";
|
||||
m_pFlareTexture = NULL;
|
||||
m_flareSize = 0.0f;
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
m_casts_shadow = true;
|
||||
m_light_shafts = true;
|
||||
m_dust_particle_density = 0.1f;
|
||||
m_dust_particle_size = 1.0f;
|
||||
m_occlusionQuery = 0;
|
||||
|
||||
// Initialize shadow buffers
|
||||
m_cShadowBuffers = 0;
|
||||
for(int iBuffer=0; iBuffer < KRENGINE_MAX_SHADOW_BUFFERS; iBuffer++) {
|
||||
shadowFramebuffer[iBuffer] = 0;
|
||||
shadowDepthTexture[iBuffer] = 0;
|
||||
shadowValid[iBuffer] = false;
|
||||
}
|
||||
}
|
||||
|
||||
KRLight::~KRLight()
|
||||
{
|
||||
if(m_occlusionQuery) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
m_occlusionQuery = 0;
|
||||
}
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("intensity", m_intensity);
|
||||
e->SetAttribute("color_r", m_color.x);
|
||||
e->SetAttribute("color_g", m_color.y);
|
||||
e->SetAttribute("color_b", m_color.z);
|
||||
e->SetAttribute("decay_start", m_decayStart);
|
||||
e->SetAttribute("flare_size", m_flareSize);
|
||||
e->SetAttribute("flare_occlusion_size", m_flareOcclusionSize);
|
||||
e->SetAttribute("flare_texture", m_flareTexture.c_str());
|
||||
e->SetAttribute("casts_shadow", m_casts_shadow ? "true" : "false");
|
||||
e->SetAttribute("light_shafts", m_light_shafts ? "true" : "false");
|
||||
e->SetAttribute("dust_particle_density", m_dust_particle_density);
|
||||
e->SetAttribute("dust_particle_size", m_dust_particle_size);
|
||||
e->SetAttribute("dust_particle_intensity", m_dust_particle_intensity);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
float x=1.0f,y=1.0f,z=1.0f;
|
||||
if(e->QueryFloatAttribute("color_r", &x) != tinyxml2::XML_SUCCESS) {
|
||||
x = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_g", &y) != tinyxml2::XML_SUCCESS) {
|
||||
y = 1.0;
|
||||
}
|
||||
if(e->QueryFloatAttribute("color_b", &z) != tinyxml2::XML_SUCCESS) {
|
||||
z = 1.0;
|
||||
}
|
||||
m_color = Vector3::Create(x,y,z);
|
||||
|
||||
if(e->QueryFloatAttribute("intensity", &m_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_intensity = 100.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("decay_start", &m_decayStart) != tinyxml2::XML_SUCCESS) {
|
||||
m_decayStart = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_size", &m_flareSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareSize = 0.0;
|
||||
}
|
||||
|
||||
if(e->QueryFloatAttribute("flare_occlusion_size", &m_flareOcclusionSize) != tinyxml2::XML_SUCCESS) {
|
||||
m_flareOcclusionSize = 0.05f;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("casts_shadow", &m_casts_shadow) != tinyxml2::XML_SUCCESS) {
|
||||
m_casts_shadow = true;
|
||||
}
|
||||
|
||||
if(e->QueryBoolAttribute("light_shafts", &m_light_shafts) != tinyxml2::XML_SUCCESS) {
|
||||
m_light_shafts = true;
|
||||
}
|
||||
|
||||
m_dust_particle_density = 0.1f;
|
||||
if(e->QueryFloatAttribute("dust_particle_density", &m_dust_particle_density) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_density = 0.1f;
|
||||
}
|
||||
|
||||
m_dust_particle_size = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_size", &m_dust_particle_size) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_size = 1.0f;
|
||||
}
|
||||
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
if(e->QueryFloatAttribute("dust_particle_intensity", &m_dust_particle_intensity) != tinyxml2::XML_SUCCESS) {
|
||||
m_dust_particle_intensity = 1.0f;
|
||||
}
|
||||
|
||||
const char *szFlareTexture = e->Attribute("flare_texture");
|
||||
if(szFlareTexture) {
|
||||
m_flareTexture = szFlareTexture;
|
||||
} else {
|
||||
m_flareTexture = "";
|
||||
}
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareTexture(std::string flare_texture) {
|
||||
m_flareTexture = flare_texture;
|
||||
m_pFlareTexture = NULL;
|
||||
}
|
||||
|
||||
void KRLight::setFlareSize(float flare_size) {
|
||||
m_flareSize = flare_size;
|
||||
}
|
||||
|
||||
void KRLight::setFlareOcclusionSize(float occlusion_size) {
|
||||
m_flareOcclusionSize = occlusion_size;
|
||||
}
|
||||
|
||||
void KRLight::setIntensity(float intensity) {
|
||||
m_intensity = intensity;
|
||||
}
|
||||
float KRLight::getIntensity() {
|
||||
return m_intensity;
|
||||
}
|
||||
|
||||
const Vector3 &KRLight::getColor() {
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void KRLight::setColor(const Vector3 &color) {
|
||||
m_color = color;
|
||||
}
|
||||
|
||||
void KRLight::setDecayStart(float decayStart) {
|
||||
m_decayStart = decayStart;
|
||||
}
|
||||
|
||||
float KRLight::getDecayStart() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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))) {
|
||||
allocateShadowBuffers(configureShadowBufferViewports(viewport));
|
||||
renderShadowBuffers(pCamera);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES && pCamera->settings.dust_particle_enable) {
|
||||
// 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(viewport.visible(getBounds()) || true) { // FINDME, HACK need to remove "|| true"?
|
||||
|
||||
float particle_range = 600.0f;
|
||||
|
||||
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;
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
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.translate(viewport.getCameraPosition());
|
||||
|
||||
std::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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().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(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color * pCamera->settings.dust_particle_intensity * m_dust_particle_intensity * m_intensity);
|
||||
pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_PARTICLE_ORIGIN, Matrix4::DotWDiv(Matrix4::Invert(particleModelMatrix), Vector3::Zero()));
|
||||
pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_FLARE_SIZE, m_dust_particle_size);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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::vector<KRDirectionalLight *> this_directional_light;
|
||||
std::vector<KRSpotLight *> this_spot_light;
|
||||
std::vector<KRPointLight *> this_point_light;
|
||||
KRDirectionalLight *directional_light = dynamic_cast<KRDirectionalLight *>(this);
|
||||
KRSpotLight *spot_light = dynamic_cast<KRSpotLight *>(this);
|
||||
KRPointLight *point_light = dynamic_cast<KRPointLight *>(this);
|
||||
if(directional_light) {
|
||||
this_directional_light.push_back(directional_light);
|
||||
}
|
||||
if(spot_light) {
|
||||
this_spot_light.push_back(spot_light);
|
||||
}
|
||||
if(point_light) {
|
||||
this_point_light.push_back(point_light);
|
||||
}
|
||||
|
||||
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().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;
|
||||
|
||||
float slice_near = -pCamera->settings.getPerspectiveNearZ();
|
||||
float slice_far = -pCamera->settings.volumetric_environment_max_distance;
|
||||
float slice_spacing = (slice_far - slice_near) / slice_count;
|
||||
|
||||
pFogShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SLICE_DEPTH_SCALE, Vector2::Create(slice_near, slice_spacing));
|
||||
pFogShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, (m_color * pCamera->settings.volumetric_environment_intensity * m_intensity * -slice_spacing / 1000.0f));
|
||||
|
||||
KRDataBlock index_data;
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_PARTICLE_OCCLUSION) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
|
||||
Matrix4 occlusion_test_sphere_matrix = Matrix4();
|
||||
occlusion_test_sphere_matrix.scale(m_localScale * m_flareOcclusionSize);
|
||||
occlusion_test_sphere_matrix.translate(m_localTranslation);
|
||||
if(m_parentNode) {
|
||||
occlusion_test_sphere_matrix *= m_parentNode->getModelMatrix();
|
||||
}
|
||||
|
||||
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));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "occlusion_test", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_flareTexture.size() && m_flareSize > 0.0f) {
|
||||
|
||||
if(m_occlusionQuery) {
|
||||
GLuint params = 0;
|
||||
GLDEBUG(glGetQueryObjectuivEXT(m_occlusionQuery, GL_QUERY_RESULT_EXT, ¶ms));
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
|
||||
if(params) {
|
||||
|
||||
if(!m_pFlareTexture && m_flareTexture.size()) {
|
||||
m_pFlareTexture = getContext().getTextureManager()->getTexture(m_flareTexture);
|
||||
}
|
||||
|
||||
if(m_pFlareTexture) {
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Render light flare on transparency pass
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, 1.0f);
|
||||
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->getMeshManager()->bindVBO(&getContext().getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KRLight::allocateShadowBuffers(int cBuffers) {
|
||||
// First deallocate buffers no longer needed
|
||||
for(int iShadow = cBuffers; iShadow < KRENGINE_MAX_SHADOW_BUFFERS; iShadow++) {
|
||||
if (shadowDepthTexture[iShadow]) {
|
||||
GLDEBUG(glDeleteTextures(1, shadowDepthTexture + iShadow));
|
||||
shadowDepthTexture[iShadow] = 0;
|
||||
}
|
||||
|
||||
if (shadowFramebuffer[iShadow]) {
|
||||
GLDEBUG(glDeleteFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
shadowFramebuffer[iShadow] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate newly required buffers
|
||||
for(int iShadow = 0; iShadow < cBuffers; iShadow++) {
|
||||
Vector2 viewportSize = m_shadowViewports[iShadow].getSize();
|
||||
|
||||
if(!shadowDepthTexture[iShadow]) {
|
||||
shadowValid[iShadow] = false;
|
||||
|
||||
GLDEBUG(glGenFramebuffers(1, shadowFramebuffer + iShadow));
|
||||
GLDEBUG(glGenTextures(1, shadowDepthTexture + iShadow));
|
||||
// ===== Create offscreen shadow framebuffer object =====
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
|
||||
// ----- Create Depth Texture for shadowFramebuffer -----
|
||||
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_MAG_FILTER, GL_NEAREST));
|
||||
m_pContext->getTextureManager()->_setWrapModeS(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
m_pContext->getTextureManager()->_setWrapModeT(shadowDepthTexture[iShadow], GL_CLAMP_TO_EDGE);
|
||||
#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_FUNC_EXT, GL_LEQUAL)); // TODO - Detect GL_EXT_shadow_samplers and only activate if available
|
||||
#endif
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
m_cShadowBuffers = cBuffers;
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
allocateShadowBuffers(0);
|
||||
}
|
||||
|
||||
void KRLight::invalidateShadowBuffers()
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
shadowValid[iShadow] = false;
|
||||
}
|
||||
}
|
||||
|
||||
int KRLight::configureShadowBufferViewports(const KRViewport &viewport)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void KRLight::renderShadowBuffers(KRCamera *pCamera)
|
||||
{
|
||||
for(int iShadow=0; iShadow < m_cShadowBuffers; iShadow++) {
|
||||
if(!shadowValid[iShadow]) {
|
||||
shadowValid[iShadow] = true;
|
||||
|
||||
GLDEBUG(glBindFramebuffer(GL_FRAMEBUFFER, shadowFramebuffer[iShadow]));
|
||||
GLDEBUG(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, shadowDepthTexture[iShadow], 0));
|
||||
|
||||
GLDEBUG(glViewport(0, 0, (GLsizei)m_shadowViewports[iShadow].getSize().x, (GLsizei)m_shadowViewports[iShadow].getSize().y));
|
||||
|
||||
GLDEBUG(glClearDepthf(0.0f));
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glViewport(1, 1, (GLsizei)m_shadowViewports[iShadow].getSize().x - 2, (GLsizei)m_shadowViewports[iShadow].getSize().y - 2));
|
||||
|
||||
GLDEBUG(glClearDepthf(1.0f));
|
||||
|
||||
GLDEBUG(glClear(GL_DEPTH_BUFFER_BIT));
|
||||
|
||||
GLDEBUG(glDisable(GL_DITHER));
|
||||
|
||||
//GLDEBUG(glCullFace(GL_BACK)); // Enable frontface culling, which eliminates some self-cast shadow artifacts
|
||||
//GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
GLDEBUG(glDisable(GL_CULL_FACE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LESS));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Disable alpha blending as we are using alpha channel for packed depth info
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
|
||||
// Use shader program
|
||||
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().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);
|
||||
|
||||
GLDEBUG(glEnable(GL_CULL_FACE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int KRLight::getShadowBufferCount()
|
||||
{
|
||||
int cBuffers=0;
|
||||
for(int iBuffer=0; iBuffer < m_cShadowBuffers; iBuffer++) {
|
||||
if(shadowValid[iBuffer]) {
|
||||
cBuffers++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return cBuffers;
|
||||
}
|
||||
|
||||
GLuint *KRLight::getShadowTextures()
|
||||
{
|
||||
return shadowDepthTexture;
|
||||
}
|
||||
|
||||
KRViewport *KRLight::getShadowViewports()
|
||||
{
|
||||
return m_shadowViewports;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,22 @@ void KRLocator::loadXML(tinyxml2::XMLElement *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;
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
#include "KRNode.h"
|
||||
#include "KRTexture.h"
|
||||
|
||||
#include "boost/variant.hpp"
|
||||
|
||||
class KRLocator : public KRNode {
|
||||
public:
|
||||
KRLocator(KRScene &scene, std::string name);
|
||||
@@ -22,10 +20,16 @@ public:
|
||||
virtual std::string getElementName();
|
||||
virtual tinyxml2::XMLElement *saveXML( tinyxml2::XMLNode *parent);
|
||||
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:
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -1,422 +1,422 @@
|
||||
//
|
||||
// KRMaterial.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 "KREngine-common.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
|
||||
#include "KRContext.h"
|
||||
|
||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
||||
m_name = szName;
|
||||
m_pAmbientMap = NULL;
|
||||
m_pDiffuseMap = NULL;
|
||||
m_pSpecularMap = NULL;
|
||||
m_pNormalMap = NULL;
|
||||
m_pReflectionMap = NULL;
|
||||
m_pReflectionCube = NULL;
|
||||
m_ambientColor = Vector3::Zero();
|
||||
m_diffuseColor = Vector3::One();
|
||||
m_specularColor = Vector3::One();
|
||||
m_reflectionColor = Vector3::Zero();
|
||||
m_tr = (GLfloat)1.0f;
|
||||
m_ns = (GLfloat)0.0f;
|
||||
m_ambientMap = "";
|
||||
m_diffuseMap = "";
|
||||
m_specularMap = "";
|
||||
m_normalMap = "";
|
||||
m_reflectionMap = "";
|
||||
m_reflectionCube = "";
|
||||
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
||||
}
|
||||
|
||||
KRMaterial::~KRMaterial() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRMaterial::getExtension() {
|
||||
return "mtl";
|
||||
}
|
||||
|
||||
bool KRMaterial::needsVertexTangents()
|
||||
{
|
||||
return m_normalMap.size() > 0;
|
||||
}
|
||||
|
||||
bool KRMaterial::save(KRDataBlock &data) {
|
||||
std::stringstream stream;
|
||||
stream.precision(std::numeric_limits<long double>::digits10);
|
||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
||||
|
||||
stream << "newmtl " << m_name;
|
||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
||||
stream << "\nTr " << m_tr;
|
||||
stream << "\nNs " << m_ns;
|
||||
if(m_ambientMap.size()) {
|
||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_diffuseMap.size()) {
|
||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
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";
|
||||
} else {
|
||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_normalMap.size()) {
|
||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionMap.size()) {
|
||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionCube.size()) {
|
||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
||||
} else {
|
||||
stream << "\n# map_ReflectionCube cubemapname";
|
||||
}
|
||||
switch(m_alpha_mode) {
|
||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
||||
stream << "\nalpha_mode opaque";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
||||
stream << "\nalpha_mode test";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
||||
stream << "\nalpha_mode blendoneside";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
||||
stream << "\nalpha_mode blendtwoside";
|
||||
break;
|
||||
}
|
||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
||||
|
||||
stream << "\n";
|
||||
data.append(stream.str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_ambientMap = texture_name;
|
||||
m_ambientMapScale = texture_scale;
|
||||
m_ambientMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_diffuseMap = texture_name;
|
||||
m_diffuseMapScale = texture_scale;
|
||||
m_diffuseMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_specularMap = texture_name;
|
||||
m_specularMapScale = texture_scale;
|
||||
m_specularMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_normalMap = texture_name;
|
||||
m_normalMapScale = texture_scale;
|
||||
m_normalMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_reflectionMap = texture_name;
|
||||
m_reflectionMapScale = texture_scale;
|
||||
m_reflectionMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
||||
m_reflectionCube = texture_name;
|
||||
}
|
||||
|
||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
||||
m_alpha_mode = alpha_mode;
|
||||
}
|
||||
|
||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
||||
return m_alpha_mode;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
||||
m_ambientColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
||||
m_diffuseColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
||||
m_specularColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflection(const Vector3 &c) {
|
||||
m_reflectionColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setTransparency(GLfloat a) {
|
||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
}
|
||||
m_tr = a;
|
||||
}
|
||||
|
||||
void KRMaterial::setShininess(GLfloat s) {
|
||||
m_ns = s;
|
||||
}
|
||||
|
||||
bool KRMaterial::isTransparent() {
|
||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
||||
}
|
||||
|
||||
void KRMaterial::preStream(float lodCoverage)
|
||||
{
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRMaterial::getStreamLevel()
|
||||
{
|
||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
||||
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
void KRMaterial::getTextures()
|
||||
{
|
||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
||||
}
|
||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
||||
}
|
||||
if(!m_pNormalMap && m_normalMap.size()) {
|
||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
||||
}
|
||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
||||
}
|
||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
||||
}
|
||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
||||
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 bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||
|
||||
getTextures();
|
||||
|
||||
Vector2 default_scale = Vector2::One();
|
||||
Vector2 default_offset = Vector2::Zero();
|
||||
|
||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
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)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind bones
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
GLfloat bone_mats[256 * 16];
|
||||
GLfloat *bone_mat_component = bone_mats;
|
||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
||||
KRBone *bone = bones[bone_index];
|
||||
|
||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
||||
// Vector3 rotation = bone->getLocalRotation();
|
||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||
// Vector3 translation = bone->getLocalTranslation();
|
||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
||||
// 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 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);
|
||||
|
||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
||||
Matrix4 t = (inv_bind_mat * active_mat);
|
||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
||||
for(int i=0; i < 16; i++) {
|
||||
*bone_mat_component++ = t[i];
|
||||
}
|
||||
}
|
||||
if(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
glUniformMatrix4fv(pShader->m_uniforms[KRShader::KRENGINE_UNIFORM_BONE_TRANSFORMS], bones.size(), GL_FALSE, bone_mats);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// 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));
|
||||
} else {
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
||||
}
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
||||
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
||||
|
||||
if(bDiffuseMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(bSpecMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(bNormalMap) {
|
||||
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)) {
|
||||
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)) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &KRMaterial::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
//
|
||||
// KRMaterial.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 "KREngine-common.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
|
||||
#include "KRContext.h"
|
||||
|
||||
KRMaterial::KRMaterial(KRContext &context, const char *szName) : KRResource(context, szName) {
|
||||
m_name = szName;
|
||||
m_pAmbientMap = NULL;
|
||||
m_pDiffuseMap = NULL;
|
||||
m_pSpecularMap = NULL;
|
||||
m_pNormalMap = NULL;
|
||||
m_pReflectionMap = NULL;
|
||||
m_pReflectionCube = NULL;
|
||||
m_ambientColor = Vector3::Zero();
|
||||
m_diffuseColor = Vector3::One();
|
||||
m_specularColor = Vector3::One();
|
||||
m_reflectionColor = Vector3::Zero();
|
||||
m_tr = (GLfloat)1.0f;
|
||||
m_ns = (GLfloat)0.0f;
|
||||
m_ambientMap = "";
|
||||
m_diffuseMap = "";
|
||||
m_specularMap = "";
|
||||
m_normalMap = "";
|
||||
m_reflectionMap = "";
|
||||
m_reflectionCube = "";
|
||||
m_ambientMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_specularMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_diffuseMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_ambientMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_specularMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_diffuseMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_reflectionMapOffset = Vector2::Create(0.0f, 0.0f);
|
||||
m_reflectionMapScale = Vector2::Create(1.0f, 1.0f);
|
||||
m_alpha_mode = KRMATERIAL_ALPHA_MODE_OPAQUE;
|
||||
}
|
||||
|
||||
KRMaterial::~KRMaterial() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRMaterial::getExtension() {
|
||||
return "mtl";
|
||||
}
|
||||
|
||||
bool KRMaterial::needsVertexTangents()
|
||||
{
|
||||
return m_normalMap.size() > 0;
|
||||
}
|
||||
|
||||
bool KRMaterial::save(KRDataBlock &data) {
|
||||
std::stringstream stream;
|
||||
stream.precision(std::numeric_limits<long double>::digits10);
|
||||
stream.setf(std::ios::fixed,std::ios::floatfield);
|
||||
|
||||
stream << "newmtl " << m_name;
|
||||
stream << "\nka " << m_ambientColor.x << " " << m_ambientColor.y << " " << m_ambientColor.z;
|
||||
stream << "\nkd " << m_diffuseColor.x << " " << m_diffuseColor.y << " " << m_diffuseColor.z;
|
||||
stream << "\nks " << m_specularColor.x << " " << m_specularColor.y << " " << m_specularColor.z;
|
||||
stream << "\nkr " << m_reflectionColor.x << " " << m_reflectionColor.y << " " << m_reflectionColor.z;
|
||||
stream << "\nTr " << m_tr;
|
||||
stream << "\nNs " << m_ns;
|
||||
if(m_ambientMap.size()) {
|
||||
stream << "\nmap_Ka " << m_ambientMap << ".pvr -s " << m_ambientMapScale.x << " " << m_ambientMapScale.y << " -o " << m_ambientMapOffset.x << " " << m_ambientMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Ka filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_diffuseMap.size()) {
|
||||
stream << "\nmap_Kd " << m_diffuseMap << ".pvr -s " << m_diffuseMapScale.x << " " << m_diffuseMapScale.y << " -o " << m_diffuseMapOffset.x << " " << m_diffuseMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Kd filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
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";
|
||||
} else {
|
||||
stream << "\n# map_Ks filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_normalMap.size()) {
|
||||
stream << "\nmap_Normal " << m_normalMap << ".pvr -s " << m_normalMapScale.x << " " << m_normalMapScale.y << " -o " << m_normalMapOffset.x << " " << m_normalMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Normal filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionMap.size()) {
|
||||
stream << "\nmap_Reflection " << m_reflectionMap << ".pvr -s " << m_reflectionMapScale.x << " " << m_reflectionMapScale.y << " -o " << m_reflectionMapOffset.x << " " << m_reflectionMapOffset.y;
|
||||
} else {
|
||||
stream << "\n# map_Reflection filename.pvr -s 1.0 1.0 -o 0.0 0.0";
|
||||
}
|
||||
if(m_reflectionCube.size()) {
|
||||
stream << "\nmap_ReflectionCube " << m_reflectionCube << ".pvr";
|
||||
} else {
|
||||
stream << "\n# map_ReflectionCube cubemapname";
|
||||
}
|
||||
switch(m_alpha_mode) {
|
||||
case KRMATERIAL_ALPHA_MODE_OPAQUE:
|
||||
stream << "\nalpha_mode opaque";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_TEST:
|
||||
stream << "\nalpha_mode test";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDONESIDE:
|
||||
stream << "\nalpha_mode blendoneside";
|
||||
break;
|
||||
case KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE:
|
||||
stream << "\nalpha_mode blendtwoside";
|
||||
break;
|
||||
}
|
||||
stream << "\n# alpha_mode opaque, test, blendoneside, or blendtwoside";
|
||||
|
||||
stream << "\n";
|
||||
data.append(stream.str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbientMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_ambientMap = texture_name;
|
||||
m_ambientMapScale = texture_scale;
|
||||
m_ambientMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuseMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_diffuseMap = texture_name;
|
||||
m_diffuseMapScale = texture_scale;
|
||||
m_diffuseMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecularMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_specularMap = texture_name;
|
||||
m_specularMapScale = texture_scale;
|
||||
m_specularMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setNormalMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_normalMap = texture_name;
|
||||
m_normalMapScale = texture_scale;
|
||||
m_normalMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionMap(std::string texture_name, Vector2 texture_scale, Vector2 texture_offset) {
|
||||
m_reflectionMap = texture_name;
|
||||
m_reflectionMapScale = texture_scale;
|
||||
m_reflectionMapOffset = texture_offset;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflectionCube(std::string texture_name) {
|
||||
m_reflectionCube = texture_name;
|
||||
}
|
||||
|
||||
void KRMaterial::setAlphaMode(KRMaterial::alpha_mode_type alpha_mode) {
|
||||
m_alpha_mode = alpha_mode;
|
||||
}
|
||||
|
||||
KRMaterial::alpha_mode_type KRMaterial::getAlphaMode() {
|
||||
return m_alpha_mode;
|
||||
}
|
||||
|
||||
void KRMaterial::setAmbient(const Vector3 &c) {
|
||||
m_ambientColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setDiffuse(const Vector3 &c) {
|
||||
m_diffuseColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setSpecular(const Vector3 &c) {
|
||||
m_specularColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setReflection(const Vector3 &c) {
|
||||
m_reflectionColor = c;
|
||||
}
|
||||
|
||||
void KRMaterial::setTransparency(GLfloat a) {
|
||||
if(a < 1.0f && m_alpha_mode == KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE) {
|
||||
setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
}
|
||||
m_tr = a;
|
||||
}
|
||||
|
||||
void KRMaterial::setShininess(GLfloat s) {
|
||||
m_ns = s;
|
||||
}
|
||||
|
||||
bool KRMaterial::isTransparent() {
|
||||
return m_tr < 1.0 || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDONESIDE || m_alpha_mode == KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE;
|
||||
}
|
||||
|
||||
void KRMaterial::preStream(float lodCoverage)
|
||||
{
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
m_pAmbientMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_AMBIENT_MAP);
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
m_pDiffuseMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
m_pNormalMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_NORMAL_MAP);
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
m_pSpecularMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
m_pReflectionMap->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFLECTION_MAP);
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
m_pReflectionCube->resetPoolExpiry(lodCoverage, KRTexture::TEXTURE_USAGE_REFECTION_CUBE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRMaterial::getStreamLevel()
|
||||
{
|
||||
kraken_stream_level stream_level = kraken_stream_level::STREAM_LEVEL_IN_HQ;
|
||||
|
||||
getTextures();
|
||||
|
||||
if(m_pAmbientMap) {
|
||||
stream_level = KRMIN(stream_level, m_pAmbientMap->getStreamLevel(KRTexture::TEXTURE_USAGE_AMBIENT_MAP));
|
||||
}
|
||||
|
||||
if(m_pDiffuseMap) {
|
||||
stream_level = KRMIN(stream_level, m_pDiffuseMap->getStreamLevel(KRTexture::TEXTURE_USAGE_DIFFUSE_MAP));
|
||||
}
|
||||
|
||||
if(m_pNormalMap) {
|
||||
stream_level = KRMIN(stream_level, m_pNormalMap->getStreamLevel(KRTexture::TEXTURE_USAGE_NORMAL_MAP));
|
||||
}
|
||||
|
||||
if(m_pSpecularMap) {
|
||||
stream_level = KRMIN(stream_level, m_pSpecularMap->getStreamLevel(KRTexture::TEXTURE_USAGE_SPECULAR_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionMap) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionMap->getStreamLevel(KRTexture::TEXTURE_USAGE_REFLECTION_MAP));
|
||||
}
|
||||
|
||||
if(m_pReflectionCube) {
|
||||
stream_level = KRMIN(stream_level, m_pReflectionCube->getStreamLevel(KRTexture::TEXTURE_USAGE_REFECTION_CUBE));
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
void KRMaterial::getTextures()
|
||||
{
|
||||
if(!m_pAmbientMap && m_ambientMap.size()) {
|
||||
m_pAmbientMap = getContext().getTextureManager()->getTexture(m_ambientMap);
|
||||
}
|
||||
if(!m_pDiffuseMap && m_diffuseMap.size()) {
|
||||
m_pDiffuseMap = getContext().getTextureManager()->getTexture(m_diffuseMap);
|
||||
}
|
||||
if(!m_pNormalMap && m_normalMap.size()) {
|
||||
m_pNormalMap = getContext().getTextureManager()->getTexture(m_normalMap);
|
||||
}
|
||||
if(!m_pSpecularMap && m_specularMap.size()) {
|
||||
m_pSpecularMap = getContext().getTextureManager()->getTexture(m_specularMap);
|
||||
}
|
||||
if(!m_pReflectionMap && m_reflectionMap.size()) {
|
||||
m_pReflectionMap = getContext().getTextureManager()->getTexture(m_reflectionMap);
|
||||
}
|
||||
if(!m_pReflectionCube && m_reflectionCube.size()) {
|
||||
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 bLightMap = pLightMap && pCamera->settings.bEnableLightMap;
|
||||
|
||||
getTextures();
|
||||
|
||||
Vector2 default_scale = Vector2::One();
|
||||
Vector2 default_offset = Vector2::Zero();
|
||||
|
||||
bool bHasReflection = m_reflectionColor != Vector3::Zero();
|
||||
bool bDiffuseMap = m_pDiffuseMap != NULL && pCamera->settings.bEnableDiffuseMap;
|
||||
bool bNormalMap = m_pNormalMap != NULL && pCamera->settings.bEnableNormalMap;
|
||||
bool bSpecMap = m_pSpecularMap != NULL && pCamera->settings.bEnableSpecMap;
|
||||
bool bReflectionMap = m_pReflectionMap != NULL && pCamera->settings.bEnableReflectionMap && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
bool bReflectionCubeMap = m_pReflectionCube != NULL && pCamera->settings.bEnableReflection && bHasReflection;
|
||||
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);
|
||||
|
||||
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;
|
||||
if(!getContext().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, matModel, point_lights, directional_lights, spot_lights, 0, renderPass, rim_color, rim_power, fade_color)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bind bones
|
||||
if(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
GLfloat bone_mats[256 * 16];
|
||||
GLfloat *bone_mat_component = bone_mats;
|
||||
for(int bone_index=0; bone_index < bones.size(); bone_index++) {
|
||||
KRBone *bone = bones[bone_index];
|
||||
|
||||
// Vector3 initialRotation = bone->getInitialLocalRotation();
|
||||
// Vector3 rotation = bone->getLocalRotation();
|
||||
// Vector3 initialTranslation = bone->getInitialLocalTranslation();
|
||||
// Vector3 translation = bone->getLocalTranslation();
|
||||
// Vector3 initialScale = bone->getInitialLocalScale();
|
||||
// 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 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);
|
||||
|
||||
Matrix4 skin_bone_bind_pose = bind_poses[bone_index];
|
||||
Matrix4 active_mat = bone->getActivePoseMatrix();
|
||||
Matrix4 inv_bind_mat = bone->getInverseBindPoseMatrix();
|
||||
Matrix4 inv_bind_mat2 = Matrix4::Invert(bind_poses[bone_index]);
|
||||
Matrix4 t = (inv_bind_mat * active_mat);
|
||||
Matrix4 t2 = inv_bind_mat2 * bone->getModelMatrix();
|
||||
for(int i=0; i < 16; i++) {
|
||||
*bone_mat_component++ = t[i];
|
||||
}
|
||||
}
|
||||
if(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS] != -1) {
|
||||
glUniformMatrix4fv(pShader->m_uniforms[KRPipeline::KRENGINE_UNIFORM_BONE_TRANSFORMS], (GLsizei)bones.size(), GL_FALSE, bone_mats);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_AMBIENT, m_ambientColor + pCamera->settings.ambient_intensity);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// We pre-multiply the light color with the material color in the forward renderer
|
||||
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 {
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_DIFFUSE, m_diffuseColor);
|
||||
}
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_OPAQUE) {
|
||||
// We pre-multiply the light color with the material color in the forward renderer
|
||||
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 {
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_SPECULAR, m_specularColor);
|
||||
}
|
||||
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_SHININESS, m_ns);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_REFLECTION, m_reflectionColor);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_DIFFUSETEXTURE_SCALE, m_diffuseMapScale);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SPECULARTEXTURE_SCALE, m_specularMapScale);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_REFLECTIONTEXTURE_SCALE, m_reflectionMapScale);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_NORMALTEXTURE_SCALE, m_normalMapScale);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_DIFFUSETEXTURE_OFFSET, m_diffuseMapOffset);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_SPECULARTEXTURE_OFFSET, m_specularMapOffset);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_REFLECTIONTEXTURE_OFFSET, m_reflectionMapOffset);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_NORMALTEXTURE_OFFSET, m_normalMapOffset);
|
||||
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_tr);
|
||||
|
||||
if(bDiffuseMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(0, m_pDiffuseMap, lod_coverage, KRTexture::TEXTURE_USAGE_DIFFUSE_MAP);
|
||||
}
|
||||
|
||||
if(bSpecMap) {
|
||||
m_pContext->getTextureManager()->selectTexture(1, m_pSpecularMap, lod_coverage, KRTexture::TEXTURE_USAGE_SPECULAR_MAP);
|
||||
}
|
||||
|
||||
if(bNormalMap) {
|
||||
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)) {
|
||||
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)) {
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string &KRMaterial::getName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRTexture.h"
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRPipelineManager.h"
|
||||
#include "KRPipeline.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRResource.h"
|
||||
#include "KRScene.h"
|
||||
|
||||
@@ -1,288 +1,306 @@
|
||||
//
|
||||
// KRMaterialManager.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 "KREngine-common.h"
|
||||
#include "KRMaterialManager.h"
|
||||
|
||||
|
||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager) : KRContextObject(context)
|
||||
{
|
||||
m_pTextureManager = pTextureManager;
|
||||
m_pShaderManager = pShaderManager;
|
||||
}
|
||||
|
||||
KRMaterialManager::~KRMaterialManager() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
||||
{
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
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 {
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
if(depth_test_enable) {
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(depth_func));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
|
||||
if(depth_write_enable) {
|
||||
GLDEBUG(glDepthMask(GL_TRUE));
|
||||
} else {
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
||||
std::string lowerName = name;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
||||
if(itr == m_materials.end()) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
||||
// Not found
|
||||
return NULL;
|
||||
} else {
|
||||
return (*itr).second;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
m_materials[lowerName] = new_material;
|
||||
}
|
||||
|
||||
bool KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
||||
KRMaterial *pMaterial = NULL;
|
||||
char szSymbol[16][256];
|
||||
data->lock();
|
||||
|
||||
char *pScan = (char *)data->getStart();
|
||||
char *pEnd = (char *)data->getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
||||
} else {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(cSymbols > 0) {
|
||||
|
||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
||||
|
||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
||||
m_materials[szSymbol[1]] = pMaterial;
|
||||
}
|
||||
if(pMaterial != NULL) {
|
||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
||||
if(cSymbols == 2) {
|
||||
if(strcmp(szSymbol[1], "test") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
} else {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
||||
}
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setAmbient(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setAmbient(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setDiffuse(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setDiffuse(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setSpecular(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setSpecular(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setReflection(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setReflection(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setTransparency(a);
|
||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setShininess(a);
|
||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
||||
// Truncate file extension
|
||||
char *pScan2 = szSymbol[1];
|
||||
char *pLastPeriod = NULL;
|
||||
while(*pScan2 != '\0') {
|
||||
if(*pScan2 == '.') {
|
||||
pLastPeriod = pScan2;
|
||||
}
|
||||
pScan2++;
|
||||
}
|
||||
if(pLastPeriod) {
|
||||
*pLastPeriod = '\0';
|
||||
}
|
||||
|
||||
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
|
||||
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
|
||||
|
||||
int iScanSymbol = 2;
|
||||
int iScaleParam = -1;
|
||||
int iOffsetParam = -1;
|
||||
while(iScanSymbol < cSymbols) {
|
||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
||||
// Scale
|
||||
iScaleParam = 0;
|
||||
iOffsetParam = -1;
|
||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
||||
// Offset
|
||||
iOffsetParam = 0;
|
||||
iScaleParam = -1;
|
||||
} else {
|
||||
char *pScan3 = szSymbol[iScanSymbol];
|
||||
float v = strtof(pScan3, &pScan3);
|
||||
if(iScaleParam == 0) {
|
||||
texture_scale.x = v;
|
||||
iScaleParam++;
|
||||
} else if(iScaleParam == 1) {
|
||||
texture_scale.y = v;
|
||||
iScaleParam++;
|
||||
} else if(iOffsetParam == 0) {
|
||||
texture_offset.x = v;
|
||||
iOffsetParam++;
|
||||
} else if(iOffsetParam == 1) {
|
||||
texture_offset.y = v;
|
||||
iOffsetParam++;
|
||||
}
|
||||
}
|
||||
iScanSymbol++;
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
||||
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 true;
|
||||
}
|
||||
//
|
||||
// KRMaterialManager.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 "KREngine-common.h"
|
||||
#include "KRMaterialManager.h"
|
||||
|
||||
|
||||
KRMaterialManager::KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager) : KRResourceManager(context)
|
||||
{
|
||||
m_pTextureManager = pTextureManager;
|
||||
m_pPipelineManager = pPipelineManager;
|
||||
}
|
||||
|
||||
KRMaterialManager::~KRMaterialManager() {
|
||||
|
||||
}
|
||||
|
||||
KRResource* KRMaterialManager::loadResource(const std::string& name, const std::string& extension, KRDataBlock* data)
|
||||
{
|
||||
if (extension.compare("mtl") == 0) {
|
||||
return load(name.c_str(), data);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
KRResource* KRMaterialManager::getResource(const std::string& name, const std::string& extension)
|
||||
{
|
||||
if (extension.compare("mtl") == 0) {
|
||||
// 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.
|
||||
return m_materials[name];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
unordered_map<std::string, KRMaterial *> &KRMaterialManager::getMaterials()
|
||||
{
|
||||
return m_materials;
|
||||
}
|
||||
|
||||
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 {
|
||||
GLDEBUG(glDisable(GL_BLEND));
|
||||
}
|
||||
|
||||
if(depth_test_enable) {
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(depth_func));
|
||||
} else {
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
}
|
||||
|
||||
if(depth_write_enable) {
|
||||
GLDEBUG(glDepthMask(GL_TRUE));
|
||||
} else {
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
KRMaterial *KRMaterialManager::getMaterial(const std::string &name) {
|
||||
std::string lowerName = name;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
|
||||
unordered_map<std::string, KRMaterial *>::iterator itr = m_materials.find(lowerName);
|
||||
if(itr == m_materials.end()) {
|
||||
KRContext::Log(KRContext::LOG_LEVEL_WARNING, "Material not found: %s", name.c_str());
|
||||
// Not found
|
||||
return NULL;
|
||||
} else {
|
||||
return (*itr).second;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
lowerName.begin(), ::tolower);
|
||||
|
||||
m_materials[lowerName] = new_material;
|
||||
}
|
||||
|
||||
KRMaterial* KRMaterialManager::load(const char *szName, KRDataBlock *data) {
|
||||
KRMaterial *pMaterial = NULL;
|
||||
char szSymbol[16][256];
|
||||
data->lock();
|
||||
|
||||
char *pScan = (char *)data->getStart();
|
||||
char *pEnd = (char *)data->getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
if(*pScan >= 'A' && *pScan <= 'Z') {
|
||||
*pDest++ = *pScan++ + 'a' - 'A'; // convert to lower case for case sensitve comparison later
|
||||
} else {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// Scan through whitespace, but don't advance to next line
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t')) {
|
||||
pScan++;
|
||||
}
|
||||
}
|
||||
|
||||
if(cSymbols > 0) {
|
||||
|
||||
if(strcmp(szSymbol[0], "newmtl") == 0 && cSymbols >= 2) {
|
||||
|
||||
pMaterial = new KRMaterial(*m_pContext, szSymbol[1]);
|
||||
m_materials[szSymbol[1]] = pMaterial;
|
||||
}
|
||||
if(pMaterial != NULL) {
|
||||
if(strcmp(szSymbol[0], "alpha_mode") == 0) {
|
||||
if(cSymbols == 2) {
|
||||
if(strcmp(szSymbol[1], "test") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_TEST);
|
||||
} else if(strcmp(szSymbol[1], "blendoneside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDONESIDE);
|
||||
} else if(strcmp(szSymbol[1], "blendtwoside") == 0) {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_BLENDTWOSIDE);
|
||||
} else {
|
||||
pMaterial->setAlphaMode(KRMaterial::KRMATERIAL_ALPHA_MODE_OPAQUE);
|
||||
}
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ka") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setAmbient(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setAmbient(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kd") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setDiffuse(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setDiffuse(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "ks") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setSpecular(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setSpecular(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "kr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float r = strtof(pScan2, &pScan2);
|
||||
if(cSymbols == 2) {
|
||||
pMaterial->setReflection(Vector3::Create(r, r, r));
|
||||
} else if(cSymbols == 4) {
|
||||
pScan2 = szSymbol[2];
|
||||
float g = strtof(pScan2, &pScan2);
|
||||
pScan2 = szSymbol[3];
|
||||
float b = strtof(pScan2, &pScan2);
|
||||
pMaterial->setReflection(Vector3::Create(r, g, b));
|
||||
}
|
||||
} else if(strcmp(szSymbol[0], "tr") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setTransparency(a);
|
||||
} else if(strcmp(szSymbol[0], "ns") == 0) {
|
||||
char *pScan2 = szSymbol[1];
|
||||
float a = strtof(pScan2, &pScan2);
|
||||
pMaterial->setShininess(a);
|
||||
} else if(strncmp(szSymbol[0], "map", 3) == 0) {
|
||||
// Truncate file extension
|
||||
char *pScan2 = szSymbol[1];
|
||||
char *pLastPeriod = NULL;
|
||||
while(*pScan2 != '\0') {
|
||||
if(*pScan2 == '.') {
|
||||
pLastPeriod = pScan2;
|
||||
}
|
||||
pScan2++;
|
||||
}
|
||||
if(pLastPeriod) {
|
||||
*pLastPeriod = '\0';
|
||||
}
|
||||
|
||||
Vector2 texture_scale = Vector2::Create(1.0f, 1.0f);
|
||||
Vector2 texture_offset = Vector2::Create(0.0f, 0.0f);
|
||||
|
||||
int iScanSymbol = 2;
|
||||
int iScaleParam = -1;
|
||||
int iOffsetParam = -1;
|
||||
while(iScanSymbol < cSymbols) {
|
||||
if(strcmp(szSymbol[iScanSymbol], "-s") == 0) {
|
||||
// Scale
|
||||
iScaleParam = 0;
|
||||
iOffsetParam = -1;
|
||||
} else if(strcmp(szSymbol[iScanSymbol], "-o") == 0) {
|
||||
// Offset
|
||||
iOffsetParam = 0;
|
||||
iScaleParam = -1;
|
||||
} else {
|
||||
char *pScan3 = szSymbol[iScanSymbol];
|
||||
float v = strtof(pScan3, &pScan3);
|
||||
if(iScaleParam == 0) {
|
||||
texture_scale.x = v;
|
||||
iScaleParam++;
|
||||
} else if(iScaleParam == 1) {
|
||||
texture_scale.y = v;
|
||||
iScaleParam++;
|
||||
} else if(iOffsetParam == 0) {
|
||||
texture_offset.x = v;
|
||||
iOffsetParam++;
|
||||
} else if(iOffsetParam == 1) {
|
||||
texture_offset.y = v;
|
||||
iOffsetParam++;
|
||||
}
|
||||
}
|
||||
iScanSymbol++;
|
||||
}
|
||||
|
||||
if(strcmp(szSymbol[0], "map_ka") == 0) {
|
||||
pMaterial->setAmbientMap(szSymbol[1], texture_scale, texture_offset);
|
||||
} else if(strcmp(szSymbol[0], "map_kd") == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -32,11 +32,10 @@
|
||||
#ifndef KRMATERIALMANAGER_H
|
||||
#define KRMATERIALMANAGER_H
|
||||
|
||||
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRMaterial.h"
|
||||
#include "KRTextureManager.h"
|
||||
#include "KRMaterialManager.h"
|
||||
@@ -44,12 +43,15 @@
|
||||
|
||||
using std::map;
|
||||
|
||||
class KRMaterialManager : public KRContextObject {
|
||||
class KRMaterialManager : public KRResourceManager {
|
||||
public:
|
||||
KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRShaderManager *pShaderManager);
|
||||
KRMaterialManager(KRContext &context, KRTextureManager *pTextureManager, KRPipelineManager *pPipelineManager);
|
||||
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);
|
||||
KRMaterial *getMaterial(const std::string &name);
|
||||
|
||||
@@ -61,7 +63,7 @@ public:
|
||||
private:
|
||||
unordered_map<std::string, KRMaterial *> m_materials;
|
||||
KRTextureManager *m_pTextureManager;
|
||||
KRShaderManager *m_pShaderManager;
|
||||
KRPipelineManager *m_pPipelineManager;
|
||||
|
||||
};
|
||||
|
||||
|
||||
3215
kraken/KRMesh.cpp
3215
kraken/KRMesh.cpp
File diff suppressed because it is too large
Load Diff
@@ -60,8 +60,7 @@ class KRNode;
|
||||
class KRMesh : public KRResource {
|
||||
|
||||
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);
|
||||
|
||||
@@ -1,69 +1,69 @@
|
||||
//
|
||||
// KRMeshCube.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 "KRMeshCube.h"
|
||||
|
||||
|
||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshCube::~KRMeshCube()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshCube.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 "KRMeshCube.h"
|
||||
|
||||
|
||||
KRMeshCube::KRMeshCube(KRContext &context) : KRMesh(context, "__cube")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshCube::~KRMeshCube()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -38,23 +38,20 @@
|
||||
#include "KRMeshQuad.h"
|
||||
#include "KRMeshSphere.h"
|
||||
|
||||
KRMeshManager::KRMeshManager(KRContext &context) : KRContextObject(context) {
|
||||
KRMeshManager::KRMeshManager(KRContext &context) : KRResourceManager(context) {
|
||||
m_currentVBO = NULL;
|
||||
m_vboMemUsed = 0;
|
||||
m_memoryTransferredThisFrame = 0;
|
||||
m_first_frame = true;
|
||||
m_streamerComplete = true;
|
||||
|
||||
addModel(new KRMeshCube(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
|
||||
addModel(new KRMeshQuad(context)); // FINDME - HACK! This needs to be fixed, as it currently segfaults
|
||||
addModel(new KRMeshCube(context));
|
||||
addModel(new KRMeshQuad(context));
|
||||
addModel(new KRMeshSphere(context));
|
||||
m_draw_call_logging_enabled = false;
|
||||
m_draw_call_log_used = false;
|
||||
|
||||
|
||||
|
||||
// ---- Initialize stock models ----
|
||||
|
||||
static const GLfloat _KRENGINE_VBO_3D_CUBE_VERTEX_DATA[] = {
|
||||
1.0, 1.0, 1.0,
|
||||
-1.0, 1.0, 1.0,
|
||||
@@ -105,6 +102,29 @@ KRMeshManager::~KRMeshManager() {
|
||||
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 *pModel = new KRMesh(*m_pContext, szName, pData);
|
||||
addModel(pModel);
|
||||
@@ -401,32 +421,32 @@ KRDataBlock &KRMeshManager::getVolumetricLightingVertexes()
|
||||
for(int iPlane=0; iPlane < KRENGINE_MAX_VOLUMETRIC_PLANES; iPlane++) {
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = -1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = -1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
vertex_data[iVertex].vertex.x = 1.0f;
|
||||
vertex_data[iVertex].vertex.y = 1.0f;
|
||||
vertex_data[iVertex].vertex.z = iPlane;
|
||||
vertex_data[iVertex].vertex.z = (GLfloat)iPlane;
|
||||
iVertex++;
|
||||
|
||||
}
|
||||
@@ -481,7 +501,7 @@ long KRMeshManager::getMemoryTransferedThisFrame()
|
||||
}
|
||||
|
||||
|
||||
int KRMeshManager::getActiveVBOCount()
|
||||
size_t KRMeshManager::getActiveVBOCount()
|
||||
{
|
||||
return m_vbosActive.size();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define KRMESHMANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRNode.h"
|
||||
@@ -40,13 +42,16 @@
|
||||
class KRContext;
|
||||
class KRMesh;
|
||||
|
||||
class KRMeshManager : public KRContextObject {
|
||||
class KRMeshManager : public KRResourceManager {
|
||||
public:
|
||||
static const int KRENGINE_MAX_VOLUMETRIC_PLANES=500;
|
||||
static const int KRENGINE_MAX_RANDOM_PARTICLES=150000;
|
||||
|
||||
KRMeshManager(KRContext &context);
|
||||
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 endFrame(float deltaTime);
|
||||
@@ -88,7 +93,7 @@ public:
|
||||
KRVBOData(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);
|
||||
long getLastFrameUsed() { return m_last_frame_used; }
|
||||
@@ -150,7 +155,7 @@ public:
|
||||
|
||||
long getMemoryTransferedThisFrame();
|
||||
|
||||
int getActiveVBOCount();
|
||||
size_t getActiveVBOCount();
|
||||
|
||||
struct draw_call_info {
|
||||
KRNode::RenderPass pass;
|
||||
|
||||
@@ -1,63 +1,63 @@
|
||||
//
|
||||
// KRMeshQuad.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 "KRMeshQuad.h"
|
||||
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.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(0.0f, 1.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back(mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshQuad.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 "KRMeshQuad.h"
|
||||
|
||||
|
||||
KRMeshQuad::KRMeshQuad(KRContext &context) : KRMesh(context, "__quad")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
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.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(0.0f, 1.0f));
|
||||
mi.uva.push_back(Vector2::Create(1.0f, 1.0f));
|
||||
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
mi.format = KRENGINE_MODEL_FORMAT_STRIP;
|
||||
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshQuad::~KRMeshQuad()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,135 +1,122 @@
|
||||
//
|
||||
// KRMeshSphere.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 "KRMeshSphere.h"
|
||||
|
||||
|
||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
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 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1 / sqrt(2.0);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
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[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[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[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];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
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;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
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++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
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()
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
// KRMeshSphere.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 "KRMeshSphere.h"
|
||||
|
||||
|
||||
KRMeshSphere::KRMeshSphere(KRContext &context) : KRMesh(context, "__sphere")
|
||||
{
|
||||
m_constant = true;
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = (int)(pow(4, iterations) * 8.0f);
|
||||
|
||||
std::vector<Triangle3> f = std::vector<Triangle3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
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 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
f[0][0] = p[0]; f[0][1] = p[3]; f[0][2] = p[4];
|
||||
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];
|
||||
f[4][0] = p[1]; f[4][1] = p[4]; f[4][2] = p[3];
|
||||
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];
|
||||
f[7][0] = p[1]; f[7][1] = p[3]; f[7][2] = p[2];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i][0].x + f[i][1].x) / 2;
|
||||
pa.y = (f[i][0].y + f[i][1].y) / 2;
|
||||
pa.z = (f[i][0].z + f[i][1].z) / 2;
|
||||
pb.x = (f[i][1].x + f[i][2].x) / 2;
|
||||
pb.y = (f[i][1].y + f[i][2].y) / 2;
|
||||
pb.z = (f[i][1].z + f[i][2].z) / 2;
|
||||
pc.x = (f[i][2].x + f[i][0].x) / 2;
|
||||
pc.y = (f[i][2].y + f[i][0].y) / 2;
|
||||
pc.z = (f[i][2].z + f[i][0].z) / 2;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
f[nt][0] = f[i][0]; f[nt][1] = pa; f[nt][2] = pc; nt++;
|
||||
f[nt][0] = pa; f[nt][1] = f[i][1]; f[nt][2] = pb; nt++;
|
||||
f[nt][0] = pb; f[nt][1] = f[i][2]; f[nt][2] = pc; nt++;
|
||||
f[i][0] = pa;
|
||||
f[i][1] = pb;
|
||||
f[i][2] = pc;
|
||||
}
|
||||
}
|
||||
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
mi.vertices.push_back(f[facet_index][0]);
|
||||
mi.vertices.push_back(f[facet_index][1]);
|
||||
mi.vertices.push_back(f[facet_index][2]);
|
||||
}
|
||||
|
||||
mi.submesh_starts.push_back(0);
|
||||
mi.submesh_lengths.push_back((int)mi.vertices.size());
|
||||
mi.material_names.push_back("");
|
||||
|
||||
|
||||
mi.format = KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
LoadData(mi, true, true);
|
||||
}
|
||||
|
||||
KRMeshSphere::~KRMeshSphere()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,263 +1,263 @@
|
||||
//
|
||||
// KRModel.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 "KREngine-common.h"
|
||||
|
||||
#include "KRModel.h"
|
||||
#include "KRContext.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) {
|
||||
m_lightMap = light_map;
|
||||
m_pLightMap = NULL;
|
||||
m_model_name = model_name;
|
||||
m_min_lod_coverage = lod_min_coverage;
|
||||
m_receivesShadow = receives_shadow;
|
||||
m_faces_camera = faces_camera;
|
||||
m_rim_color = rim_color;
|
||||
m_rim_power = rim_power;
|
||||
|
||||
m_boundsCachedMat.c[0] = -1.0f;
|
||||
m_boundsCachedMat.c[1] = -1.0f;
|
||||
m_boundsCachedMat.c[2] = -1.0f;
|
||||
m_boundsCachedMat.c[3] = -1.0f;
|
||||
m_boundsCachedMat.c[4] = -1.0f;
|
||||
m_boundsCachedMat.c[5] = -1.0f;
|
||||
m_boundsCachedMat.c[6] = -1.0f;
|
||||
m_boundsCachedMat.c[7] = -1.0f;
|
||||
m_boundsCachedMat.c[8] = -1.0f;
|
||||
m_boundsCachedMat.c[9] = -1.0f;
|
||||
m_boundsCachedMat.c[10] = -1.0f;
|
||||
m_boundsCachedMat.c[11] = -1.0f;
|
||||
m_boundsCachedMat.c[12] = -1.0f;
|
||||
m_boundsCachedMat.c[13] = -1.0f;
|
||||
m_boundsCachedMat.c[14] = -1.0f;
|
||||
m_boundsCachedMat.c[15] = -1.0f;
|
||||
}
|
||||
|
||||
KRModel::~KRModel() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRModel::getElementName() {
|
||||
return "model";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
||||
e->SetAttribute("rim_power", m_rim_power);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
||||
{
|
||||
m_rim_color = rim_color;
|
||||
}
|
||||
|
||||
void KRModel::setRimPower(float rim_power)
|
||||
{
|
||||
m_rim_power = rim_power;
|
||||
}
|
||||
|
||||
Vector3 KRModel::getRimColor()
|
||||
{
|
||||
return m_rim_color;
|
||||
}
|
||||
|
||||
float KRModel::getRimPower()
|
||||
{
|
||||
return m_rim_power;
|
||||
}
|
||||
|
||||
void KRModel::setLightMap(const std::string &name)
|
||||
{
|
||||
m_lightMap = name;
|
||||
m_pLightMap = NULL;
|
||||
}
|
||||
|
||||
std::string KRModel::getLightMap()
|
||||
{
|
||||
return m_lightMap;
|
||||
}
|
||||
|
||||
void KRModel::loadModel() {
|
||||
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
|
||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
||||
if(models.size() > 0) {
|
||||
bool all_bones_found = true;
|
||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
||||
KRMesh *model = *model_itr;
|
||||
std::vector<KRBone *> model_bones;
|
||||
int bone_count = model->getBoneCount();
|
||||
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)));
|
||||
if(matching_bone) {
|
||||
model_bones.push_back(matching_bone);
|
||||
} else {
|
||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
||||
}
|
||||
}
|
||||
bones[model] = model_bones;
|
||||
}
|
||||
if(all_bones_found) {
|
||||
m_models = models;
|
||||
m_bones = bones;
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
preStream(viewport);
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
|
||||
if(m_models.size() > 0) {
|
||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
||||
|
||||
/*
|
||||
float lod_coverage = 0.0f;
|
||||
if(m_models.size() > 1) {
|
||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
} else if(viewport.visible(getBounds())) {
|
||||
lod_coverage = 1.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
|
||||
if(lod_coverage > m_min_lod_coverage) {
|
||||
|
||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
||||
KRMesh *pModel = *itr++;
|
||||
|
||||
while(itr != m_models.end()) {
|
||||
KRMesh *pLODModel = *itr++;
|
||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
||||
pModel = pLODModel;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Matrix4 matModel = getModelMatrix();
|
||||
if(m_faces_camera) {
|
||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
||||
Vector3 camera_pos = viewport.getCameraPosition();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::preStream(const KRViewport &viewport)
|
||||
{
|
||||
loadModel();
|
||||
float lod_coverage = viewport.coverage(getBounds());
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
(*itr)->preStream(lod_coverage);
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap) {
|
||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
||||
{
|
||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
||||
|
||||
loadModel();
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
AABB KRModel::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
if(m_faces_camera) {
|
||||
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
float max_dimension = normal_bounds.longest_radius();
|
||||
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
|
||||
} else {
|
||||
|
||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||
m_boundsCachedMat = getModelMatrix();
|
||||
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
}
|
||||
return m_boundsCached;
|
||||
}
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// KRModel.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 "KREngine-common.h"
|
||||
|
||||
#include "KRModel.h"
|
||||
#include "KRContext.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) {
|
||||
m_lightMap = light_map;
|
||||
m_pLightMap = NULL;
|
||||
m_model_name = model_name;
|
||||
m_min_lod_coverage = lod_min_coverage;
|
||||
m_receivesShadow = receives_shadow;
|
||||
m_faces_camera = faces_camera;
|
||||
m_rim_color = rim_color;
|
||||
m_rim_power = rim_power;
|
||||
|
||||
m_boundsCachedMat.c[0] = -1.0f;
|
||||
m_boundsCachedMat.c[1] = -1.0f;
|
||||
m_boundsCachedMat.c[2] = -1.0f;
|
||||
m_boundsCachedMat.c[3] = -1.0f;
|
||||
m_boundsCachedMat.c[4] = -1.0f;
|
||||
m_boundsCachedMat.c[5] = -1.0f;
|
||||
m_boundsCachedMat.c[6] = -1.0f;
|
||||
m_boundsCachedMat.c[7] = -1.0f;
|
||||
m_boundsCachedMat.c[8] = -1.0f;
|
||||
m_boundsCachedMat.c[9] = -1.0f;
|
||||
m_boundsCachedMat.c[10] = -1.0f;
|
||||
m_boundsCachedMat.c[11] = -1.0f;
|
||||
m_boundsCachedMat.c[12] = -1.0f;
|
||||
m_boundsCachedMat.c[13] = -1.0f;
|
||||
m_boundsCachedMat.c[14] = -1.0f;
|
||||
m_boundsCachedMat.c[15] = -1.0f;
|
||||
}
|
||||
|
||||
KRModel::~KRModel() {
|
||||
|
||||
}
|
||||
|
||||
std::string KRModel::getElementName() {
|
||||
return "model";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRModel::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("mesh", m_model_name.c_str());
|
||||
e->SetAttribute("light_map", m_lightMap.c_str());
|
||||
e->SetAttribute("lod_min_coverage", m_min_lod_coverage);
|
||||
e->SetAttribute("receives_shadow", m_receivesShadow ? "true" : "false");
|
||||
e->SetAttribute("faces_camera", m_faces_camera ? "true" : "false");
|
||||
kraken::setXMLAttribute("rim_color", e, m_rim_color, Vector3::Zero());
|
||||
e->SetAttribute("rim_power", m_rim_power);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRModel::setRimColor(const Vector3 &rim_color)
|
||||
{
|
||||
m_rim_color = rim_color;
|
||||
}
|
||||
|
||||
void KRModel::setRimPower(float rim_power)
|
||||
{
|
||||
m_rim_power = rim_power;
|
||||
}
|
||||
|
||||
Vector3 KRModel::getRimColor()
|
||||
{
|
||||
return m_rim_color;
|
||||
}
|
||||
|
||||
float KRModel::getRimPower()
|
||||
{
|
||||
return m_rim_power;
|
||||
}
|
||||
|
||||
void KRModel::setLightMap(const std::string &name)
|
||||
{
|
||||
m_lightMap = name;
|
||||
m_pLightMap = NULL;
|
||||
}
|
||||
|
||||
std::string KRModel::getLightMap()
|
||||
{
|
||||
return m_lightMap;
|
||||
}
|
||||
|
||||
void KRModel::loadModel() {
|
||||
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
|
||||
unordered_map<KRMesh *, std::vector<KRBone *> > bones;
|
||||
if(models.size() > 0) {
|
||||
bool all_bones_found = true;
|
||||
for(std::vector<KRMesh *>::iterator model_itr = models.begin(); model_itr != models.end(); model_itr++) {
|
||||
KRMesh *model = *model_itr;
|
||||
std::vector<KRBone *> model_bones;
|
||||
int bone_count = model->getBoneCount();
|
||||
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)));
|
||||
if(matching_bone) {
|
||||
model_bones.push_back(matching_bone);
|
||||
} else {
|
||||
all_bones_found = false; // Reject when there are any missing bones or multiple matches
|
||||
}
|
||||
}
|
||||
bones[model] = model_bones;
|
||||
}
|
||||
if(all_bones_found) {
|
||||
m_models = models;
|
||||
m_bones = bones;
|
||||
getScene().notify_sceneGraphModify(this);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
preStream(viewport);
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
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) {
|
||||
loadModel();
|
||||
|
||||
if(m_models.size() > 0) {
|
||||
// Don't render meshes on second pass of the deferred lighting renderer, as only lights will be applied
|
||||
|
||||
/*
|
||||
float lod_coverage = 0.0f;
|
||||
if(m_models.size() > 1) {
|
||||
lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
} else if(viewport.visible(getBounds())) {
|
||||
lod_coverage = 1.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
float lod_coverage = viewport.coverage(getBounds()); // This also checks the view frustrum culling
|
||||
|
||||
if(lod_coverage > m_min_lod_coverage) {
|
||||
|
||||
// ---===--- Select the best LOD model based on screen coverage ---===---
|
||||
std::vector<KRMesh *>::iterator itr=m_models.begin();
|
||||
KRMesh *pModel = *itr++;
|
||||
|
||||
while(itr != m_models.end()) {
|
||||
KRMesh *pLODModel = *itr++;
|
||||
if((float)pLODModel->getLODCoverage() / 100.0f > lod_coverage && pLODModel->getLODCoverage() < pModel->getLODCoverage()) {
|
||||
pModel = pLODModel;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Matrix4 matModel = getModelMatrix();
|
||||
if(m_faces_camera) {
|
||||
Vector3 model_center = Matrix4::Dot(matModel, Vector3::Zero());
|
||||
Vector3 camera_pos = viewport.getCameraPosition();
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRModel::preStream(const KRViewport &viewport)
|
||||
{
|
||||
loadModel();
|
||||
float lod_coverage = viewport.coverage(getBounds());
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
(*itr)->preStream(lod_coverage);
|
||||
}
|
||||
|
||||
if(m_pLightMap == NULL && m_lightMap.size()) {
|
||||
m_pLightMap = getContext().getTextureManager()->getTexture(m_lightMap);
|
||||
}
|
||||
|
||||
if(m_pLightMap) {
|
||||
m_pLightMap->resetPoolExpiry(lod_coverage, KRTexture::TEXTURE_USAGE_LIGHT_MAP);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kraken_stream_level KRModel::getStreamLevel(const KRViewport &viewport)
|
||||
{
|
||||
kraken_stream_level stream_level = KRNode::getStreamLevel(viewport);
|
||||
|
||||
loadModel();
|
||||
|
||||
for(auto itr = m_models.begin(); itr != m_models.end(); itr++) {
|
||||
stream_level = KRMIN(stream_level, (*itr)->getStreamLevel());
|
||||
}
|
||||
|
||||
return stream_level;
|
||||
}
|
||||
|
||||
AABB KRModel::getBounds() {
|
||||
loadModel();
|
||||
if(m_models.size() > 0) {
|
||||
if(m_faces_camera) {
|
||||
AABB normal_bounds = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
float max_dimension = normal_bounds.longest_radius();
|
||||
return AABB::Create(normal_bounds.center()-Vector3::Create(max_dimension), normal_bounds.center() + Vector3::Create(max_dimension));
|
||||
} else {
|
||||
|
||||
if(!(m_boundsCachedMat == getModelMatrix())) {
|
||||
m_boundsCachedMat = getModelMatrix();
|
||||
m_boundsCached = AABB::Create(m_models[0]->getMinPoint(), m_models[0]->getMaxPoint(), getModelMatrix());
|
||||
}
|
||||
return m_boundsCached;
|
||||
}
|
||||
} else {
|
||||
return AABB::Infinite();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1926
kraken/KRNode.cpp
1926
kraken/KRNode.cpp
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ class Matrix4;
|
||||
class AABB;
|
||||
} // namespace kraken
|
||||
class KRCamera;
|
||||
class KRShaderManager;
|
||||
class KRPipelineManager;
|
||||
class KRMeshManager;
|
||||
class KRMaterialManager;
|
||||
class KRTextureManager;
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
//
|
||||
// KROctree.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "public/kraken.h"
|
||||
#include "KROctree.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctree::KROctree()
|
||||
{
|
||||
m_pRootNode = NULL;
|
||||
}
|
||||
|
||||
KROctree::~KROctree()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
delete m_pRootNode;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::add(KRNode *pNode)
|
||||
{
|
||||
AABB nodeBounds = pNode->getBounds();
|
||||
if(nodeBounds == AABB::Zero()) {
|
||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||
} else if(nodeBounds == AABB::Infinite()) {
|
||||
// This item is infinitely large; we track it separately
|
||||
m_outerSceneNodes.insert(pNode);
|
||||
} else {
|
||||
if(m_pRootNode == NULL) {
|
||||
// First item inserted, create a node large enough to fit it
|
||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||
m_pRootNode->add(pNode);
|
||||
} else {
|
||||
// Keep encapsulating the root node until the new root contains the inserted node
|
||||
bool bInsideRoot = false;
|
||||
while(!bInsideRoot) {
|
||||
AABB rootBounds = m_pRootNode->getBounds();
|
||||
Vector3 rootSize = rootBounds.size();
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
bInsideRoot = true;
|
||||
}
|
||||
}
|
||||
m_pRootNode->add(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::remove(KRNode *pNode)
|
||||
{
|
||||
if(!m_outerSceneNodes.erase(pNode)) {
|
||||
if(m_pRootNode) {
|
||||
pNode->removeFromOctreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::update(KRNode *pNode)
|
||||
{
|
||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||
remove(pNode);
|
||||
add(pNode);
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::shrink()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
while(m_pRootNode->canShrinkRoot()) {
|
||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||
delete m_pRootNode;
|
||||
m_pRootNode = newRoot;
|
||||
if(m_pRootNode == NULL) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KROctreeNode *KROctree::getRootNode()
|
||||
{
|
||||
return m_pRootNode;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||
{
|
||||
return m_outerSceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
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(m_pRootNode) {
|
||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
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(m_pRootNode) {
|
||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
//
|
||||
// KROctree.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "public/kraken.h"
|
||||
#include "KROctree.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctree::KROctree()
|
||||
{
|
||||
m_pRootNode = NULL;
|
||||
}
|
||||
|
||||
KROctree::~KROctree()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
delete m_pRootNode;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::add(KRNode *pNode)
|
||||
{
|
||||
AABB nodeBounds = pNode->getBounds();
|
||||
if(nodeBounds == AABB::Zero()) {
|
||||
// This item is not visible, don't add it to the octree or outer scene nodes
|
||||
} else if(nodeBounds == AABB::Infinite()) {
|
||||
// This item is infinitely large; we track it separately
|
||||
m_outerSceneNodes.insert(pNode);
|
||||
} else {
|
||||
if(m_pRootNode == NULL) {
|
||||
// First item inserted, create a node large enough to fit it
|
||||
m_pRootNode = new KROctreeNode(NULL, nodeBounds);
|
||||
m_pRootNode->add(pNode);
|
||||
} else {
|
||||
// Keep encapsulating the root node until the new root contains the inserted node
|
||||
bool bInsideRoot = false;
|
||||
while(!bInsideRoot) {
|
||||
AABB rootBounds = m_pRootNode->getBounds();
|
||||
Vector3 rootSize = rootBounds.size();
|
||||
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);
|
||||
} 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);
|
||||
} else {
|
||||
bInsideRoot = true;
|
||||
}
|
||||
}
|
||||
m_pRootNode->add(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctree::remove(KRNode *pNode)
|
||||
{
|
||||
if(!m_outerSceneNodes.erase(pNode)) {
|
||||
if(m_pRootNode) {
|
||||
pNode->removeFromOctreeNodes();
|
||||
}
|
||||
}
|
||||
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::update(KRNode *pNode)
|
||||
{
|
||||
// TODO: This may be more efficient as an incremental operation rather than removing and re-adding the node
|
||||
remove(pNode);
|
||||
add(pNode);
|
||||
shrink();
|
||||
}
|
||||
|
||||
void KROctree::shrink()
|
||||
{
|
||||
if(m_pRootNode) {
|
||||
while(m_pRootNode->canShrinkRoot()) {
|
||||
KROctreeNode *newRoot = m_pRootNode->stripChild();
|
||||
delete m_pRootNode;
|
||||
m_pRootNode = newRoot;
|
||||
if(m_pRootNode == NULL) return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
KROctreeNode *KROctree::getRootNode()
|
||||
{
|
||||
return m_pRootNode;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctree::getOuterSceneNodes()
|
||||
{
|
||||
return m_outerSceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctree::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
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(m_pRootNode) {
|
||||
if(m_pRootNode->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
if(m_pRootNode) {
|
||||
if(m_pRootNode->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctree::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
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++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*outer_nodes_itr);
|
||||
if(collider) {
|
||||
outer_colliders.push_back(collider);
|
||||
}
|
||||
}
|
||||
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(m_pRootNode) {
|
||||
if(m_pRootNode->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,290 +1,290 @@
|
||||
//
|
||||
// KROctreeNode.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
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
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
m_children[iChild] = pChild;
|
||||
pChild->m_parent = this;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::~KROctreeNode()
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i] != NULL) {
|
||||
delete m_children[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(m_occlusionTested) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KROctreeNode::beginOcclusionQuery()
|
||||
{
|
||||
if(!m_occlusionTested){
|
||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||
#if TARGET_OS_IPHONE
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
m_occlusionTested = true;
|
||||
m_activeQuery = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::endOcclusionQuery()
|
||||
{
|
||||
if(m_activeQuery) {
|
||||
// Only end a query if we started one
|
||||
#if TARGET_OS_IPHONE
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AABB KROctreeNode::getBounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
void KROctreeNode::add(KRNode *pNode)
|
||||
{
|
||||
int iChild = getChildIndex(pNode);
|
||||
if(iChild == -1) {
|
||||
m_sceneNodes.insert(pNode);
|
||||
pNode->addToOctreeNode(this);
|
||||
} else {
|
||||
if(m_children[iChild] == NULL) {
|
||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||
}
|
||||
m_children[iChild]->add(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
AABB KROctreeNode::getChildBounds(int iChild)
|
||||
{
|
||||
Vector3 center = m_bounds.center();
|
||||
|
||||
return AABB::Create(
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||
);
|
||||
}
|
||||
|
||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||
{
|
||||
for(int iChild=0; iChild < 8; iChild++) {
|
||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||
return iChild;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KROctreeNode::trim()
|
||||
{
|
||||
for(int iChild = 0; iChild < 8; iChild++) {
|
||||
if(m_children[iChild]) {
|
||||
if(m_children[iChild]->isEmpty()) {
|
||||
delete m_children[iChild];
|
||||
m_children[iChild] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::remove(KRNode *pNode)
|
||||
{
|
||||
m_sceneNodes.erase(pNode);
|
||||
}
|
||||
|
||||
void KROctreeNode::update(KRNode *pNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KROctreeNode::isEmpty() const
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
bool KROctreeNode::canShrinkRoot() const
|
||||
{
|
||||
int cChildren = 0;
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
cChildren++;
|
||||
}
|
||||
}
|
||||
return cChildren <= 1 && m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
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
|
||||
// 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++) {
|
||||
if(m_children[i]) {
|
||||
KROctreeNode *child = m_children[i];
|
||||
child->m_parent = NULL;
|
||||
m_children[i] = NULL;
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
KROctreeNode *KROctreeNode::getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
KROctreeNode **KROctreeNode::getChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||
{
|
||||
return m_sceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||
} else {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit()) {
|
||||
// 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
|
||||
} else {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
/*
|
||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||
} 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));
|
||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||
if(getBounds().intersects(swept_bounds)) {
|
||||
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
//
|
||||
// KROctreeNode.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-08-29.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KROctreeNode.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRCollider.h"
|
||||
|
||||
KROctreeNode::KROctreeNode(KROctreeNode *parent, const AABB &bounds) : m_bounds(bounds)
|
||||
{
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
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
|
||||
m_parent = parent;
|
||||
|
||||
for(int i=0; i<8; i++) m_children[i] = NULL;
|
||||
m_children[iChild] = pChild;
|
||||
pChild->m_parent = this;
|
||||
|
||||
m_occlusionQuery = 0;
|
||||
m_occlusionTested = false;
|
||||
m_activeQuery = false;
|
||||
}
|
||||
|
||||
KROctreeNode::~KROctreeNode()
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i] != NULL) {
|
||||
delete m_children[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(m_occlusionTested) {
|
||||
GLDEBUG(glDeleteQueriesEXT(1, &m_occlusionQuery));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KROctreeNode::beginOcclusionQuery()
|
||||
{
|
||||
if(!m_occlusionTested){
|
||||
GLDEBUG(glGenQueriesEXT(1, &m_occlusionQuery));
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glBeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, m_occlusionQuery));
|
||||
#else
|
||||
GLDEBUG(glBeginQuery(GL_SAMPLES_PASSED, m_occlusionQuery));
|
||||
#endif
|
||||
m_occlusionTested = true;
|
||||
m_activeQuery = true;
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::endOcclusionQuery()
|
||||
{
|
||||
if(m_activeQuery) {
|
||||
// Only end a query if we started one
|
||||
#if TARGET_OS_IPHONE || defined(ANDROID)
|
||||
GLDEBUG(glEndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT));
|
||||
#else
|
||||
GLDEBUG(glEndQuery(GL_SAMPLES_PASSED));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AABB KROctreeNode::getBounds()
|
||||
{
|
||||
return m_bounds;
|
||||
}
|
||||
|
||||
void KROctreeNode::add(KRNode *pNode)
|
||||
{
|
||||
int iChild = getChildIndex(pNode);
|
||||
if(iChild == -1) {
|
||||
m_sceneNodes.insert(pNode);
|
||||
pNode->addToOctreeNode(this);
|
||||
} else {
|
||||
if(m_children[iChild] == NULL) {
|
||||
m_children[iChild] = new KROctreeNode(this, getChildBounds(iChild));
|
||||
}
|
||||
m_children[iChild]->add(pNode);
|
||||
}
|
||||
}
|
||||
|
||||
AABB KROctreeNode::getChildBounds(int iChild)
|
||||
{
|
||||
Vector3 center = m_bounds.center();
|
||||
|
||||
return AABB::Create(
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? m_bounds.min.x : center.x,
|
||||
(iChild & 2) == 0 ? m_bounds.min.y : center.y,
|
||||
(iChild & 4) == 0 ? m_bounds.min.z : center.z),
|
||||
Vector3::Create(
|
||||
(iChild & 1) == 0 ? center.x : m_bounds.max.x,
|
||||
(iChild & 2) == 0 ? center.y : m_bounds.max.y,
|
||||
(iChild & 4) == 0 ? center.z : m_bounds.max.z)
|
||||
);
|
||||
}
|
||||
|
||||
int KROctreeNode::getChildIndex(KRNode *pNode)
|
||||
{
|
||||
for(int iChild=0; iChild < 8; iChild++) {
|
||||
if(getChildBounds(iChild).contains(pNode->getBounds())) {
|
||||
return iChild;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void KROctreeNode::trim()
|
||||
{
|
||||
for(int iChild = 0; iChild < 8; iChild++) {
|
||||
if(m_children[iChild]) {
|
||||
if(m_children[iChild]->isEmpty()) {
|
||||
delete m_children[iChild];
|
||||
m_children[iChild] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KROctreeNode::remove(KRNode *pNode)
|
||||
{
|
||||
m_sceneNodes.erase(pNode);
|
||||
}
|
||||
|
||||
void KROctreeNode::update(KRNode *pNode)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KROctreeNode::isEmpty() const
|
||||
{
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
bool KROctreeNode::canShrinkRoot() const
|
||||
{
|
||||
int cChildren = 0;
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
cChildren++;
|
||||
}
|
||||
}
|
||||
return cChildren <= 1 && m_sceneNodes.empty();
|
||||
}
|
||||
|
||||
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
|
||||
// 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++) {
|
||||
if(m_children[i]) {
|
||||
KROctreeNode *child = m_children[i];
|
||||
child->m_parent = NULL;
|
||||
m_children[i] = NULL;
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
KROctreeNode *KROctreeNode::getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
KROctreeNode **KROctreeNode::getChildren()
|
||||
{
|
||||
return m_children;
|
||||
}
|
||||
|
||||
std::set<KRNode *> &KROctreeNode::getSceneNodes()
|
||||
{
|
||||
return m_sceneNodes;
|
||||
}
|
||||
|
||||
|
||||
bool KROctreeNode::lineCast(const Vector3 &v0, const Vector3 &v1, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = lineCast(v0, hitinfo.getPosition(), hitinfo, layer_mask);
|
||||
} else {
|
||||
if(getBounds().intersectsLine(v0, v1)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->lineCast(v0, v1, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->lineCast(v0, v1, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::rayCast(const Vector3 &v0, const Vector3 &dir, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
if(hitinfo.didHit()) {
|
||||
// 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
|
||||
} else {
|
||||
if(getBounds().intersectsRay(v0, dir)) {
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->rayCast(v0, dir, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->rayCast(v0, dir, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
bool KROctreeNode::sphereCast(const Vector3 &v0, const Vector3 &v1, float radius, HitInfo &hitinfo, unsigned int layer_mask)
|
||||
{
|
||||
bool hit_found = false;
|
||||
/*
|
||||
// FINDME, TODO - Adapt this optimization to work with sphereCasts
|
||||
|
||||
if(hitinfo.didHit() && v1 != hitinfo.getPosition()) {
|
||||
// Optimization: If we already have a hit, only search for hits that are closer
|
||||
hit_found = sphereCast(v0, hitinfo.getPosition(), radius, hitinfo, layer_mask);
|
||||
} 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));
|
||||
// FINDME, TODO - Investigate AABB - swept sphere intersections or OBB - AABB intersections: "if(getBounds().intersectsSweptSphere(v0, v1, radius)) {"
|
||||
if(getBounds().intersects(swept_bounds)) {
|
||||
|
||||
for(std::set<KRNode *>::iterator nodes_itr=m_sceneNodes.begin(); nodes_itr != m_sceneNodes.end(); nodes_itr++) {
|
||||
KRCollider *collider = dynamic_cast<KRCollider *>(*nodes_itr);
|
||||
if(collider) {
|
||||
if(collider->sphereCast(v0, v1, radius, hitinfo, layer_mask)) hit_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i=0; i<8; i++) {
|
||||
if(m_children[i]) {
|
||||
if(m_children[i]->sphereCast(v0, v1, radius, hitinfo, layer_mask)) {
|
||||
hit_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// }
|
||||
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
//
|
||||
// KRParticleSystemNewtonian.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRParticleSystemNewtonian.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
|
||||
{
|
||||
m_particlesAbsoluteTime = 0.0f;
|
||||
}
|
||||
|
||||
KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRParticleSystemNewtonian::getElementName()
|
||||
{
|
||||
return "newtonian_particles";
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRParticleSystem::loadXML(e);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
AABB KRParticleSystemNewtonian::getBounds()
|
||||
{
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
|
||||
{
|
||||
KRParticleSystem::physicsUpdate(deltaTime);
|
||||
m_particlesAbsoluteTime += deltaTime;
|
||||
}
|
||||
|
||||
bool KRParticleSystemNewtonian::hasPhysics()
|
||||
{
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(viewport.visible(getBounds())) {
|
||||
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
|
||||
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
|
||||
|
||||
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);
|
||||
|
||||
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())) {
|
||||
pParticleShader->setUniform(KRShader::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRParticleSystemNewtonian.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-11-02.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRParticleSystemNewtonian.h"
|
||||
#include "KRTexture.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRParticleSystemNewtonian::KRParticleSystemNewtonian(KRScene &scene, std::string name) : KRParticleSystem(scene, name)
|
||||
{
|
||||
m_particlesAbsoluteTime = 0.0f;
|
||||
}
|
||||
|
||||
KRParticleSystemNewtonian::~KRParticleSystemNewtonian()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRParticleSystemNewtonian::getElementName()
|
||||
{
|
||||
return "newtonian_particles";
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRParticleSystem::loadXML(e);
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRParticleSystemNewtonian::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRParticleSystem::saveXML(parent);
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
AABB KRParticleSystemNewtonian::getBounds()
|
||||
{
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
void KRParticleSystemNewtonian::physicsUpdate(float deltaTime)
|
||||
{
|
||||
KRParticleSystem::physicsUpdate(deltaTime);
|
||||
m_particlesAbsoluteTime += deltaTime;
|
||||
}
|
||||
|
||||
bool KRParticleSystemNewtonian::hasPhysics()
|
||||
{
|
||||
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) {
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(viewport.visible(getBounds())) {
|
||||
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
KRTexture *pParticleTexture = m_pContext->getTextureManager()->getTexture("flare");
|
||||
m_pContext->getTextureManager()->selectTexture(0, pParticleTexture, 0.0f, KRTexture::TEXTURE_USAGE_PARTICLE);
|
||||
|
||||
int particle_count = 10000;
|
||||
|
||||
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;
|
||||
if(getContext().getPipelineManager()->selectPipeline(*pCamera, pParticleShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
pParticleShader->setUniform(KRPipeline::KRENGINE_UNIFORM_FLARE_SIZE, 1.0f);
|
||||
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, particle_count*3));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
581
kraken/KRPipeline.cpp
Normal file
581
kraken/KRPipeline.cpp
Normal 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
161
kraken/KRPipeline.h
Normal 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
|
||||
273
kraken/KRPipelineManager.cpp
Normal file
273
kraken/KRPipelineManager.cpp
Normal 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();
|
||||
}
|
||||
69
kraken/KRPipelineManager.h
Normal file
69
kraken/KRPipelineManager.h
Normal 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
|
||||
@@ -1,226 +1,226 @@
|
||||
//
|
||||
// KRPointLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRPointLight.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
m_sphereVertices = NULL;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
|
||||
KRPointLight::~KRPointLight()
|
||||
{
|
||||
if(m_sphereVertices) {
|
||||
delete m_sphereVertices;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRPointLight::getElementName() {
|
||||
return "point_light";
|
||||
}
|
||||
|
||||
AABB KRPointLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRPointLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Vector3 light_position = getLocalTranslation();
|
||||
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
|
||||
Matrix4 sphereModelMatrix = Matrix4();
|
||||
sphereModelMatrix.scale(influence_radius);
|
||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||
|
||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||
|
||||
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());
|
||||
|
||||
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);
|
||||
if(getContext().getShaderManager()->selectShader(*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(KRShader::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||
pShader->setUniform(KRShader::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||
|
||||
|
||||
if(bVisualize) {
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
}
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
|
||||
if(bInsideLight) {
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
} else {
|
||||
#if GL_OES_vertex_array_object
|
||||
GLDEBUG(glBindVertexArrayOES(0));
|
||||
#endif
|
||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
// Render sphere of light's influence
|
||||
generateMesh();
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||
}
|
||||
}
|
||||
if(bVisualize) {
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRPointLight::generateMesh() {
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = pow(4, iterations) * 8;
|
||||
|
||||
if(m_cVertices != facet_count * 3) {
|
||||
if(m_sphereVertices) {
|
||||
free(m_sphereVertices);
|
||||
m_sphereVertices = NULL;
|
||||
}
|
||||
|
||||
m_cVertices = facet_count * 3;
|
||||
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
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 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
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[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[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[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];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
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;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
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++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||
assert(m_sphereVertices != NULL);
|
||||
GLfloat *pDest = m_sphereVertices;
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
*pDest++ = f[facet_index].p1.x;
|
||||
*pDest++ = f[facet_index].p1.y;
|
||||
*pDest++ = f[facet_index].p1.z;
|
||||
*pDest++ = f[facet_index].p2.x;
|
||||
*pDest++ = f[facet_index].p2.y;
|
||||
*pDest++ = f[facet_index].p2.z;
|
||||
*pDest++ = f[facet_index].p3.x;
|
||||
*pDest++ = f[facet_index].p3.y;
|
||||
*pDest++ = f[facet_index].p3.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRPointLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRPointLight.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRStockGeometry.h"
|
||||
|
||||
KRPointLight::KRPointLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
m_sphereVertices = NULL;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
|
||||
KRPointLight::~KRPointLight()
|
||||
{
|
||||
if(m_sphereVertices) {
|
||||
delete m_sphereVertices;
|
||||
m_cVertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRPointLight::getElementName() {
|
||||
return "point_light";
|
||||
}
|
||||
|
||||
AABB KRPointLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRLight::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && pCamera->settings.bShowDeferred;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_DEFERRED_LIGHTS || bVisualize) {
|
||||
// Lights are rendered on the second pass of the deferred renderer
|
||||
|
||||
std::vector<KRPointLight *> this_light;
|
||||
this_light.push_back(this);
|
||||
|
||||
Vector3 light_position = getLocalTranslation();
|
||||
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
|
||||
Matrix4 sphereModelMatrix = Matrix4();
|
||||
sphereModelMatrix.scale(influence_radius);
|
||||
sphereModelMatrix.translate(light_position.x, light_position.y, light_position.z);
|
||||
|
||||
if(viewport.visible(getBounds())) { // Cull out any lights not within the view frustrum
|
||||
|
||||
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());
|
||||
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, this_light, std::vector<KRDirectionalLight *>(), std::vector<KRSpotLight *>(), 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_COLOR, m_color);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_INTENSITY, m_intensity * 0.01f);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_DECAY_START, getDecayStart());
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_CUTOFF, KRLIGHT_MIN_INFLUENCE);
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_LIGHT_POSITION, light_position);
|
||||
|
||||
|
||||
if(bVisualize) {
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
}
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
|
||||
if(bInsideLight) {
|
||||
|
||||
// Disable z-buffer test
|
||||
GLDEBUG(glDisable(GL_DEPTH_TEST));
|
||||
|
||||
// Render a full screen quad
|
||||
m_pContext->getMeshManager()->bindVBO(&m_pContext->getMeshManager()->KRENGINE_VBO_DATA_2D_SQUARE_VERTICES, 1.0f);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
} else {
|
||||
#if GL_OES_vertex_array_object
|
||||
GLDEBUG(glBindVertexArrayOES(0));
|
||||
#endif
|
||||
m_pContext->getMeshManager()->configureAttribs(1 << KRMesh::KRENGINE_ATTRIB_VERTEX);
|
||||
// Render sphere of light's influence
|
||||
generateMesh();
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
GLDEBUG(glVertexAttribPointer(KRMesh::KRENGINE_ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, m_sphereVertices));
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLES, 0, m_cVertices));
|
||||
}
|
||||
}
|
||||
if(bVisualize) {
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KRPointLight::generateMesh() {
|
||||
// Create a triangular facet approximation to a sphere
|
||||
// Based on algorithm from Paul Bourke: http://paulbourke.net/miscellaneous/sphere_cylinder/
|
||||
|
||||
int iterations = 3;
|
||||
int facet_count = (int)(pow(4, iterations) * 8);
|
||||
|
||||
if(m_cVertices != facet_count * 3) {
|
||||
if(m_sphereVertices) {
|
||||
free(m_sphereVertices);
|
||||
m_sphereVertices = NULL;
|
||||
}
|
||||
|
||||
m_cVertices = facet_count * 3;
|
||||
|
||||
|
||||
class Facet3 {
|
||||
public:
|
||||
Facet3() {
|
||||
|
||||
}
|
||||
~Facet3() {
|
||||
|
||||
}
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
Vector3 p3;
|
||||
};
|
||||
|
||||
std::vector<Facet3> f = std::vector<Facet3>(facet_count);
|
||||
|
||||
int i,it;
|
||||
float a;
|
||||
Vector3 p[6] = {
|
||||
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 pa,pb,pc;
|
||||
int nt = 0,ntold;
|
||||
|
||||
/* Create the level 0 object */
|
||||
a = 1.0f / sqrtf(2.0f);
|
||||
for (i=0;i<6;i++) {
|
||||
p[i].x *= a;
|
||||
p[i].y *= a;
|
||||
}
|
||||
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[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[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[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];
|
||||
nt = 8;
|
||||
|
||||
/* Bisect each edge and move to the surface of a unit sphere */
|
||||
for (it=0;it<iterations;it++) {
|
||||
ntold = nt;
|
||||
for (i=0;i<ntold;i++) {
|
||||
pa.x = (f[i].p1.x + f[i].p2.x) / 2;
|
||||
pa.y = (f[i].p1.y + f[i].p2.y) / 2;
|
||||
pa.z = (f[i].p1.z + f[i].p2.z) / 2;
|
||||
pb.x = (f[i].p2.x + f[i].p3.x) / 2;
|
||||
pb.y = (f[i].p2.y + f[i].p3.y) / 2;
|
||||
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;
|
||||
pa.normalize();
|
||||
pb.normalize();
|
||||
pc.normalize();
|
||||
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++;
|
||||
f[i].p1 = pa;
|
||||
f[i].p2 = pb;
|
||||
f[i].p3 = pc;
|
||||
}
|
||||
}
|
||||
|
||||
m_sphereVertices = (GLfloat *)malloc(sizeof(GLfloat) * m_cVertices * 3);
|
||||
assert(m_sphereVertices != NULL);
|
||||
GLfloat *pDest = m_sphereVertices;
|
||||
for(int facet_index=0; facet_index < facet_count; facet_index++) {
|
||||
*pDest++ = f[facet_index].p1.x;
|
||||
*pDest++ = f[facet_index].p1.y;
|
||||
*pDest++ = f[facet_index].p1.z;
|
||||
*pDest++ = f[facet_index].p2.x;
|
||||
*pDest++ = f[facet_index].p2.y;
|
||||
*pDest++ = f[facet_index].p2.z;
|
||||
*pDest++ = f[facet_index].p3.x;
|
||||
*pDest++ = f[facet_index].p3.y;
|
||||
*pDest++ = f[facet_index].p3.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,204 +1,204 @@
|
||||
//
|
||||
// KRRenderSettings.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRRenderSettings.h"
|
||||
|
||||
KRRenderSettings::KRRenderSettings()
|
||||
{
|
||||
siren_enable = true;
|
||||
siren_enable_reverb = true;
|
||||
siren_enable_hrtf = true;
|
||||
siren_reverb_max_length = 2.0f;
|
||||
|
||||
m_enable_realtime_occlusion = false;
|
||||
bShowShadowBuffer = false;
|
||||
bShowOctree = false;
|
||||
bShowDeferred = false;
|
||||
bEnablePerPixel = true;
|
||||
bEnableDiffuseMap = true;
|
||||
bEnableNormalMap = true;
|
||||
bEnableSpecMap = true;
|
||||
bEnableReflectionMap = true;
|
||||
bEnableReflection = true;
|
||||
bDebugPSSM = false;
|
||||
bEnableAmbient = true;
|
||||
bEnableDiffuse = true;
|
||||
bEnableSpecular = true;
|
||||
bEnableLightMap = true;
|
||||
bEnableDeferredLighting = false;
|
||||
max_anisotropy = 4.0f;
|
||||
|
||||
ambient_intensity = Vector3::Zero();
|
||||
light_intensity = Vector3::One();
|
||||
|
||||
perspective_fov = 45.0f * D2R;
|
||||
perspective_nearz = 0.3f; // was 0.05f
|
||||
perspective_farz = 1000.0f;
|
||||
|
||||
dof_quality = 0;
|
||||
dof_depth = 0.05f;
|
||||
dof_falloff = 0.05f;
|
||||
|
||||
bEnableFlash = false;
|
||||
flash_intensity = 1.0f;
|
||||
flash_depth = 0.7f;
|
||||
flash_falloff = 0.5f;
|
||||
|
||||
|
||||
bEnableVignette = false;
|
||||
vignette_radius = 0.4f;
|
||||
vignette_falloff = 1.0f;
|
||||
|
||||
|
||||
m_cShadowBuffers = 0;
|
||||
|
||||
volumetric_environment_enable = false;
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 100.0f;
|
||||
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 50.0f;
|
||||
fog_far = 500.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
|
||||
fog_type = 0;
|
||||
|
||||
dust_particle_intensity = 0.25f;
|
||||
dust_particle_enable = false;
|
||||
|
||||
m_lodBias = 0.0f;
|
||||
|
||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||
}
|
||||
|
||||
KRRenderSettings::~KRRenderSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||
{
|
||||
siren_enable = s.siren_enable;
|
||||
siren_enable_reverb = s.siren_enable_reverb;
|
||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||
|
||||
bEnablePerPixel = s.bEnablePerPixel;
|
||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||
bEnableNormalMap = s.bEnableNormalMap;
|
||||
bEnableSpecMap = s.bEnableSpecMap;
|
||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||
bEnableReflection=s.bEnableReflection;
|
||||
bEnableLightMap=s.bEnableLightMap;
|
||||
bDebugPSSM=s.bDebugPSSM;
|
||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||
bShowOctree=s.bShowOctree;
|
||||
bShowDeferred=s.bShowDeferred;
|
||||
bEnableAmbient=s.bEnableAmbient;
|
||||
bEnableDiffuse=s.bEnableDiffuse;
|
||||
bEnableSpecular=s.bEnableSpecular;
|
||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||
light_intensity=s.light_intensity;
|
||||
ambient_intensity=s.ambient_intensity;
|
||||
perspective_fov=s.perspective_fov;
|
||||
|
||||
dof_quality=s.dof_quality;
|
||||
dof_depth=s.dof_depth;
|
||||
dof_falloff=s.dof_falloff;
|
||||
bEnableFlash=s.bEnableFlash;
|
||||
flash_intensity=s.flash_intensity;
|
||||
flash_depth=s.flash_depth;
|
||||
flash_falloff=s.flash_falloff;
|
||||
|
||||
bEnableVignette=s.bEnableVignette;
|
||||
vignette_radius=s.vignette_radius;
|
||||
vignette_falloff=s.vignette_falloff;
|
||||
|
||||
m_viewportSize=s.m_viewportSize;
|
||||
|
||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||
|
||||
m_debug_text=s.m_debug_text;
|
||||
|
||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||
|
||||
fog_near=s.fog_near;
|
||||
fog_far=s.fog_far;
|
||||
fog_density=s.fog_density;
|
||||
fog_color=s.fog_color;
|
||||
fog_type=s.fog_type;
|
||||
|
||||
dust_particle_intensity=s.dust_particle_intensity;
|
||||
dust_particle_enable=s.dust_particle_enable;
|
||||
perspective_nearz=s.perspective_nearz;
|
||||
perspective_farz=s.perspective_farz;
|
||||
debug_display = s.debug_display;
|
||||
|
||||
m_lodBias = s.m_lodBias;
|
||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||
|
||||
max_anisotropy = s.max_anisotropy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector2 &KRRenderSettings::getViewportSize() {
|
||||
return m_viewportSize;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
||||
m_viewportSize = size;
|
||||
}
|
||||
|
||||
float KRRenderSettings::getPerspectiveNearZ()
|
||||
{
|
||||
return perspective_nearz;
|
||||
}
|
||||
float KRRenderSettings::getPerspectiveFarZ()
|
||||
{
|
||||
return perspective_farz;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setPerspectiveNear(float v)
|
||||
{
|
||||
if(perspective_nearz != v) {
|
||||
perspective_nearz = v;
|
||||
}
|
||||
}
|
||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||
{
|
||||
if(perspective_farz != v) {
|
||||
perspective_farz = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRRenderSettings::getLODBias()
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setLODBias(float v)
|
||||
{
|
||||
m_lodBias = v;
|
||||
}
|
||||
|
||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||
{
|
||||
return m_enable_realtime_occlusion;
|
||||
}
|
||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||
{
|
||||
m_enable_realtime_occlusion = enable;
|
||||
//
|
||||
// KRRenderSettings.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-20.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRRenderSettings.h"
|
||||
|
||||
KRRenderSettings::KRRenderSettings()
|
||||
{
|
||||
siren_enable = true;
|
||||
siren_enable_reverb = true;
|
||||
siren_enable_hrtf = true;
|
||||
siren_reverb_max_length = 2.0f;
|
||||
|
||||
m_enable_realtime_occlusion = false;
|
||||
bShowShadowBuffer = false;
|
||||
bShowOctree = false;
|
||||
bShowDeferred = false;
|
||||
bEnablePerPixel = true;
|
||||
bEnableDiffuseMap = true;
|
||||
bEnableNormalMap = true;
|
||||
bEnableSpecMap = true;
|
||||
bEnableReflectionMap = true;
|
||||
bEnableReflection = true;
|
||||
bDebugPSSM = false;
|
||||
bEnableAmbient = true;
|
||||
bEnableDiffuse = true;
|
||||
bEnableSpecular = true;
|
||||
bEnableLightMap = true;
|
||||
bEnableDeferredLighting = false;
|
||||
max_anisotropy = 4.0f;
|
||||
|
||||
ambient_intensity = Vector3::Zero();
|
||||
light_intensity = Vector3::One();
|
||||
|
||||
perspective_fov = 45.0f * D2R;
|
||||
perspective_nearz = 0.3f; // was 0.05f
|
||||
perspective_farz = 1000.0f;
|
||||
|
||||
dof_quality = 0;
|
||||
dof_depth = 0.05f;
|
||||
dof_falloff = 0.05f;
|
||||
|
||||
bEnableFlash = false;
|
||||
flash_intensity = 1.0f;
|
||||
flash_depth = 0.7f;
|
||||
flash_falloff = 0.5f;
|
||||
|
||||
|
||||
bEnableVignette = false;
|
||||
vignette_radius = 0.4f;
|
||||
vignette_falloff = 1.0f;
|
||||
|
||||
|
||||
m_cShadowBuffers = 0;
|
||||
|
||||
volumetric_environment_enable = false;
|
||||
volumetric_environment_downsample = 2;
|
||||
volumetric_environment_max_distance = 100.0f;
|
||||
volumetric_environment_quality = (50.0f - 5.0f) / 495.0f;
|
||||
volumetric_environment_intensity = 0.9f;
|
||||
|
||||
|
||||
fog_near = 50.0f;
|
||||
fog_far = 500.0f;
|
||||
fog_density = 0.0005f;
|
||||
fog_color = Vector3::Create(0.45f, 0.45f, 0.5f);
|
||||
fog_type = 0;
|
||||
|
||||
dust_particle_intensity = 0.25f;
|
||||
dust_particle_enable = false;
|
||||
|
||||
m_lodBias = 0.0f;
|
||||
|
||||
debug_display = KRENGINE_DEBUG_DISPLAY_NONE;
|
||||
}
|
||||
|
||||
KRRenderSettings::~KRRenderSettings()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRRenderSettings& KRRenderSettings::operator=(const KRRenderSettings &s)
|
||||
{
|
||||
siren_enable = s.siren_enable;
|
||||
siren_enable_reverb = s.siren_enable_reverb;
|
||||
siren_enable_hrtf = s.siren_enable_hrtf;
|
||||
siren_reverb_max_length = s.siren_reverb_max_length;
|
||||
|
||||
bEnablePerPixel = s.bEnablePerPixel;
|
||||
bEnableDiffuseMap = s.bEnableDiffuseMap;
|
||||
bEnableNormalMap = s.bEnableNormalMap;
|
||||
bEnableSpecMap = s.bEnableSpecMap;
|
||||
bEnableReflectionMap = s.bEnableReflectionMap;
|
||||
bEnableReflection=s.bEnableReflection;
|
||||
bEnableLightMap=s.bEnableLightMap;
|
||||
bDebugPSSM=s.bDebugPSSM;
|
||||
bShowShadowBuffer=s.bShowShadowBuffer;
|
||||
bShowOctree=s.bShowOctree;
|
||||
bShowDeferred=s.bShowDeferred;
|
||||
bEnableAmbient=s.bEnableAmbient;
|
||||
bEnableDiffuse=s.bEnableDiffuse;
|
||||
bEnableSpecular=s.bEnableSpecular;
|
||||
bEnableDeferredLighting=s.bEnableDeferredLighting;
|
||||
light_intensity=s.light_intensity;
|
||||
ambient_intensity=s.ambient_intensity;
|
||||
perspective_fov=s.perspective_fov;
|
||||
|
||||
dof_quality=s.dof_quality;
|
||||
dof_depth=s.dof_depth;
|
||||
dof_falloff=s.dof_falloff;
|
||||
bEnableFlash=s.bEnableFlash;
|
||||
flash_intensity=s.flash_intensity;
|
||||
flash_depth=s.flash_depth;
|
||||
flash_falloff=s.flash_falloff;
|
||||
|
||||
bEnableVignette=s.bEnableVignette;
|
||||
vignette_radius=s.vignette_radius;
|
||||
vignette_falloff=s.vignette_falloff;
|
||||
|
||||
m_viewportSize=s.m_viewportSize;
|
||||
|
||||
m_cShadowBuffers=s.m_cShadowBuffers;
|
||||
|
||||
m_debug_text=s.m_debug_text;
|
||||
|
||||
volumetric_environment_enable=s.volumetric_environment_enable;
|
||||
volumetric_environment_downsample=s.volumetric_environment_downsample;
|
||||
volumetric_environment_max_distance=s.volumetric_environment_max_distance;
|
||||
volumetric_environment_quality=s.volumetric_environment_quality;
|
||||
volumetric_environment_intensity=s.volumetric_environment_intensity;
|
||||
|
||||
fog_near=s.fog_near;
|
||||
fog_far=s.fog_far;
|
||||
fog_density=s.fog_density;
|
||||
fog_color=s.fog_color;
|
||||
fog_type=s.fog_type;
|
||||
|
||||
dust_particle_intensity=s.dust_particle_intensity;
|
||||
dust_particle_enable=s.dust_particle_enable;
|
||||
perspective_nearz=s.perspective_nearz;
|
||||
perspective_farz=s.perspective_farz;
|
||||
debug_display = s.debug_display;
|
||||
|
||||
m_lodBias = s.m_lodBias;
|
||||
m_enable_realtime_occlusion = s.m_enable_realtime_occlusion;
|
||||
|
||||
max_anisotropy = s.max_anisotropy;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Vector2 &KRRenderSettings::getViewportSize() {
|
||||
return m_viewportSize;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setViewportSize(const Vector2 &size) {
|
||||
m_viewportSize = size;
|
||||
}
|
||||
|
||||
float KRRenderSettings::getPerspectiveNearZ()
|
||||
{
|
||||
return perspective_nearz;
|
||||
}
|
||||
float KRRenderSettings::getPerspectiveFarZ()
|
||||
{
|
||||
return perspective_farz;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setPerspectiveNear(float v)
|
||||
{
|
||||
if(perspective_nearz != v) {
|
||||
perspective_nearz = v;
|
||||
}
|
||||
}
|
||||
void KRRenderSettings::setPerpsectiveFarZ(float v)
|
||||
{
|
||||
if(perspective_farz != v) {
|
||||
perspective_farz = v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRRenderSettings::getLODBias()
|
||||
{
|
||||
return m_lodBias;
|
||||
}
|
||||
|
||||
void KRRenderSettings::setLODBias(float v)
|
||||
{
|
||||
m_lodBias = v;
|
||||
}
|
||||
|
||||
bool KRRenderSettings::getEnableRealtimeOcclusion()
|
||||
{
|
||||
return m_enable_realtime_occlusion;
|
||||
}
|
||||
void KRRenderSettings::setEnableRealtimeOcclusion(bool enable)
|
||||
{
|
||||
m_enable_realtime_occlusion = enable;
|
||||
}
|
||||
@@ -13,10 +13,8 @@
|
||||
#include "KRResource+blend.h"
|
||||
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadBlenderScene(KRContext &context, const std::string& path) {
|
||||
std::vector<KRResource *> resources;
|
||||
KRScene* KRResource::LoadBlenderScene(KRContext &context, const std::string& path) {
|
||||
KRScene *pScene = new KRScene(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(pScene);
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
@@ -24,7 +22,7 @@ std::vector<KRResource *> KRResource::LoadBlenderScene(KRContext &context, const
|
||||
//KRBlendFile blend_file = KRBlendFile(pFile);
|
||||
}
|
||||
|
||||
return resources;
|
||||
return pScene;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include <boost/tokenizer.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/variant.hpp>
|
||||
#include "fbxsdk.h"
|
||||
|
||||
|
||||
|
||||
@@ -1,341 +1,338 @@
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
std::vector<KRResource *> KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||
{
|
||||
std::vector<KRResource *> resources;
|
||||
|
||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||
resources.push_back(new_mesh);
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
char szSymbol[500][256];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
if(data.load(path)) {
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)data.getStart();
|
||||
char *pEnd = (char *)data.getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// 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) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
||||
assert(pFaces != NULL);
|
||||
|
||||
std::vector<Vector3> indexed_vertices;
|
||||
std::vector<Vector2> indexed_uva;
|
||||
std::vector<Vector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)data.getStart();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// 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;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(Vector2::Create(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = pFace - pMaterialFaces - 1;
|
||||
*pFace++ = 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;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace;
|
||||
++pFace;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
Vector3 firstFaceVertex;
|
||||
Vector3 prevFaceVertex;
|
||||
Vector3 firstFaceNormal;
|
||||
Vector3 prevFaceNormal;
|
||||
Vector2 firstFaceUva;
|
||||
Vector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
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
|
||||
iVertex+=2;
|
||||
|
||||
mi.vertices.push_back(firstFaceVertex);
|
||||
mi.uva.push_back(firstFaceUva);
|
||||
mi.normals.push_back(firstFaceNormal);
|
||||
|
||||
mi.vertices.push_back(prevFaceVertex);
|
||||
mi.uva.push_back(prevFaceUva);
|
||||
mi.normals.push_back(prevFaceNormal);
|
||||
}
|
||||
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
Vector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
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);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 256, 0);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
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) {
|
||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
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;
|
||||
// std::vector<std::vector<int> > bone_indexes;
|
||||
// std::vector<std::vector<float> > bone_weights;
|
||||
//
|
||||
// std::vector<__uint16_t> vertex_indexes;
|
||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
|
||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
new_mesh->LoadData(mi, true, false);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return resources;
|
||||
}
|
||||
//
|
||||
// KRResource_obj.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResource.h"
|
||||
#include "KRMesh.h"
|
||||
|
||||
KRMesh* KRResource::LoadObj(KRContext &context, const std::string& path)
|
||||
{
|
||||
KRMesh *new_mesh = new KRMesh(context, KRResource::GetFileBase(path));
|
||||
|
||||
KRMesh::mesh_info mi;
|
||||
|
||||
std::vector<std::string> material_names_t;
|
||||
|
||||
KRDataBlock data;
|
||||
|
||||
char szSymbol[500][256];
|
||||
|
||||
int *pFaces = NULL;
|
||||
|
||||
vector<KRMesh::pack_material *> m_materials;
|
||||
|
||||
if(data.load(path)) {
|
||||
// -----=====----- Get counts -----=====-----
|
||||
|
||||
int cVertexData = 0;
|
||||
|
||||
|
||||
int cFaces = 1;
|
||||
int cMaterialFaceStart = 1;
|
||||
|
||||
char *pScan = (char *)data.getStart();
|
||||
char *pEnd = (char *)data.getEnd();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// 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) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertexes = (cSymbols - 3) * 3; // 3 vertexes per triangle. Triangles have 4 symbols. Quads have 5 symbols and generate two triangles.
|
||||
cVertexData += cFaceVertexes;
|
||||
cFaces += cFaceVertexes * 3 + 1; // Allocate space for count of vertices, Vertex Index, Texture Coordinate Index, and Normal Index
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(cMaterialFaceStart - cFaces > 0) {
|
||||
cFaces++;
|
||||
|
||||
}
|
||||
material_names_t.push_back(std::string(szSymbol[1]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----=====----- Populate vertexes and faces -----=====-----
|
||||
|
||||
int *pFaces = (int *)malloc(sizeof(int) * (cFaces + 1));
|
||||
assert(pFaces != NULL);
|
||||
|
||||
std::vector<Vector3> indexed_vertices;
|
||||
std::vector<Vector2> indexed_uva;
|
||||
std::vector<Vector3> indexed_normals;
|
||||
|
||||
int *pFace = pFaces;
|
||||
int *pMaterialFaces = pFace++;
|
||||
*pMaterialFaces = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
// --------
|
||||
|
||||
pScan = (char *)data.getStart();
|
||||
while(pScan < pEnd) {
|
||||
|
||||
// Scan through whitespace
|
||||
while(pScan < pEnd && (*pScan == ' ' || *pScan == '\t' || *pScan == '\r' || *pScan == '\n')) {
|
||||
pScan++;
|
||||
}
|
||||
|
||||
if(*pScan == '#') {
|
||||
// Line is a comment line
|
||||
|
||||
// Scan to the end of the line
|
||||
while(pScan < pEnd && *pScan != '\r' && *pScan != '\n') {
|
||||
pScan++;
|
||||
}
|
||||
} else {
|
||||
int cSymbols = 0;
|
||||
while(pScan < pEnd && *pScan != '\n' && *pScan != '\r') {
|
||||
|
||||
char *pDest = szSymbol[cSymbols++];
|
||||
while(pScan < pEnd && *pScan != ' ' && *pScan != '\n' && *pScan != '\r') {
|
||||
*pDest++ = *pScan++;
|
||||
}
|
||||
*pDest = '\0';
|
||||
|
||||
// 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;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_vertices.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "vt") == 0) {
|
||||
// Vertex Texture UV Coordinate (vt)
|
||||
char *pChar = szSymbol[1];
|
||||
float u,v;
|
||||
|
||||
u = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
v = strtof(pChar, &pChar);
|
||||
indexed_uva.push_back(Vector2::Create(u,v));
|
||||
} else if(strcmp(szSymbol[0], "vn") == 0) {
|
||||
// Vertex Normal (vn)
|
||||
float x,y,z;
|
||||
char *pChar = szSymbol[1];
|
||||
x = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[2];
|
||||
y = strtof(pChar, &pChar);
|
||||
pChar = szSymbol[3];
|
||||
z = strtof(pChar, &pChar);
|
||||
indexed_normals.push_back(Vector3::Create(x,y,z));
|
||||
} else if(strcmp(szSymbol[0], "f") == 0) {
|
||||
// Face (f)
|
||||
int cFaceVertices = cSymbols - 1;
|
||||
|
||||
*pFace++ = cFaceVertices;
|
||||
for(int iSymbol=1; iSymbol < cSymbols; iSymbol++) {
|
||||
char *pChar = szSymbol[iSymbol];
|
||||
if(*pChar == '.' || (*pChar >= '0' && *pChar <= '9')) {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Vertex Index
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Texture Coordinate Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
|
||||
if(*pChar == '/') {
|
||||
pChar++;
|
||||
if(*pChar == '/') {
|
||||
*pFace++ = -1;
|
||||
} else {
|
||||
*pFace++ = strtol(pChar, &pChar, 10) - 1; // Normal Index
|
||||
}
|
||||
} else {
|
||||
*pFace++ = -1;
|
||||
}
|
||||
while(*pChar == '/') {
|
||||
pChar++;
|
||||
strtol(pChar, &pChar, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} else if(strcmp(szSymbol[0], "usemtl") == 0) {
|
||||
// Use Material (usemtl)
|
||||
if(pFace - pMaterialFaces > 1) {
|
||||
*pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
|
||||
pMaterialFaces = pFace++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
*pMaterialFaces = (int)(pFace - pMaterialFaces - 1);
|
||||
*pFace++ = 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;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 0, 256);
|
||||
if(material_itr < material_names_t.end()) {
|
||||
strncpy(pMaterial->szName, (*material_itr++).c_str(), 256);
|
||||
}
|
||||
m_materials.push_back(pMaterial);
|
||||
|
||||
|
||||
pFace = pFaces;
|
||||
while(*pFace != 0 && iVertex < cVertexData) {
|
||||
pMaterial->start_vertex = iVertex;
|
||||
|
||||
int *pMaterialEndFace = pFace + *pFace;
|
||||
++pFace;
|
||||
while(pFace < pMaterialEndFace && iVertex < cVertexData) {
|
||||
int cFaceVertexes = *pFace;
|
||||
Vector3 firstFaceVertex;
|
||||
Vector3 prevFaceVertex;
|
||||
Vector3 firstFaceNormal;
|
||||
Vector3 prevFaceNormal;
|
||||
Vector2 firstFaceUva;
|
||||
Vector2 prevFaceUva;
|
||||
for(int iFaceVertex=0; iFaceVertex < cFaceVertexes; iFaceVertex++) {
|
||||
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
|
||||
iVertex+=2;
|
||||
|
||||
mi.vertices.push_back(firstFaceVertex);
|
||||
mi.uva.push_back(firstFaceUva);
|
||||
mi.normals.push_back(firstFaceNormal);
|
||||
|
||||
mi.vertices.push_back(prevFaceVertex);
|
||||
mi.uva.push_back(prevFaceUva);
|
||||
mi.normals.push_back(prevFaceNormal);
|
||||
}
|
||||
Vector3 vertex = indexed_vertices[pFace[iFaceVertex*3+1]];
|
||||
Vector2 new_uva;
|
||||
if(pFace[iFaceVertex*3+2] >= 0) {
|
||||
new_uva = indexed_uva[pFace[iFaceVertex*3+2]];
|
||||
}
|
||||
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);
|
||||
|
||||
if(iFaceVertex==0) {
|
||||
firstFaceVertex = vertex;
|
||||
firstFaceUva = new_uva;
|
||||
firstFaceNormal = normal;
|
||||
}
|
||||
prevFaceVertex = vertex;
|
||||
prevFaceUva = new_uva;
|
||||
prevFaceNormal = normal;
|
||||
|
||||
iVertex++;
|
||||
}
|
||||
pFace += cFaceVertexes * 3 + 1;
|
||||
}
|
||||
pMaterial->vertex_count = iVertex - pMaterial->start_vertex;
|
||||
if(*pFace != 0) {
|
||||
pMaterial = new KRMesh::pack_material();
|
||||
pMaterial->start_vertex = iVertex;
|
||||
pMaterial->vertex_count = 0;
|
||||
memset(pMaterial->szName, 0, 256);
|
||||
|
||||
if(material_itr < material_names_t.end()) {
|
||||
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) {
|
||||
mi.material_names.push_back(std::string(pNewMaterial->szName));
|
||||
mi.submesh_starts.push_back(pNewMaterial->start_vertex);
|
||||
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;
|
||||
// std::vector<std::vector<int> > bone_indexes;
|
||||
// std::vector<std::vector<float> > bone_weights;
|
||||
//
|
||||
// std::vector<__uint16_t> vertex_indexes;
|
||||
// std::vector<std::pair<int, int> > vertex_index_bases;
|
||||
|
||||
mi.format = KRMesh::KRENGINE_MODEL_FORMAT_TRIANGLES;
|
||||
new_mesh->LoadData(mi, true, false);
|
||||
}
|
||||
|
||||
if(pFaces) {
|
||||
free(pFaces);
|
||||
}
|
||||
|
||||
return new_mesh;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRResource.h"
|
||||
#include "KRBundle.h"
|
||||
|
||||
KRResource::KRResource(KRContext &context, std::string name) : KRContextObject(context) {
|
||||
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 f = name;
|
||||
|
||||
// Normalize Windows Paths
|
||||
std::replace(f.begin(), f.end(), '\\', '/');
|
||||
|
||||
// Strip off directory
|
||||
if(f.find_last_of("/") != std::string::npos) {
|
||||
f = f.substr(f.find_last_of("/") + 1);
|
||||
@@ -63,4 +68,15 @@ bool KRResource::save(const std::string& path)
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -1,47 +1,50 @@
|
||||
//
|
||||
// KRResource.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
#ifndef KRRESOURCE_H
|
||||
#define KRRESOURCE_H
|
||||
|
||||
class KRResource : public KRContextObject
|
||||
{
|
||||
public:
|
||||
std::string getName();
|
||||
virtual std::string getExtension() = 0;
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data) = 0;
|
||||
|
||||
static std::string GetFileExtension(const std::string& name);
|
||||
static std::string GetFileBase(const std::string& name);
|
||||
static std::string GetFilePath(const std::string& name);
|
||||
|
||||
virtual ~KRResource();
|
||||
|
||||
|
||||
static std::vector<KRResource *> LoadObj(KRContext &context, const std::string& path);
|
||||
#if !TARGET_OS_IPHONE
|
||||
static void LoadFbx(KRContext &context, const std::string& path);
|
||||
static std::vector<KRResource *> LoadBlenderScene(KRContext &context, const std::string& path);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
KRResource(KRContext &context, std::string name);
|
||||
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
//
|
||||
// KRResource.h
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-03-22.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
#ifndef KRRESOURCE_H
|
||||
#define KRRESOURCE_H
|
||||
class KRBundle;
|
||||
class KRScene;
|
||||
class KRMesh;
|
||||
class KRResource : public KRContextObject
|
||||
{
|
||||
public:
|
||||
std::string getName();
|
||||
virtual std::string getExtension() = 0;
|
||||
virtual bool save(const std::string& path);
|
||||
virtual bool save(KRDataBlock &data) = 0;
|
||||
|
||||
KrResult moveToBundle(KRBundle* bundle);
|
||||
|
||||
static std::string GetFileExtension(const std::string& name);
|
||||
static std::string GetFileBase(const std::string& name);
|
||||
static std::string GetFilePath(const std::string& name);
|
||||
|
||||
virtual ~KRResource();
|
||||
|
||||
static KRMesh* LoadObj(KRContext &context, const std::string& path);
|
||||
#if !TARGET_OS_IPHONE
|
||||
// static KRScene* LoadFbx(KRContext &context, const std::string& path); TODO, FINDME, HACK! - Uncomment
|
||||
static KRScene* LoadBlenderScene(KRContext &context, const std::string& path);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
KRResource(KRContext &context, std::string name);
|
||||
|
||||
|
||||
private:
|
||||
std::string m_name;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
17
kraken_standard_assets_ios/Shaders/occlusion_test.fsh → kraken/KRResourceManager.cpp
Executable file → Normal file
17
kraken_standard_assets_ios/Shaders/occlusion_test.fsh → kraken/KRResourceManager.cpp
Executable file → Normal file
@@ -1,8 +1,8 @@
|
||||
//
|
||||
// flare.fsh
|
||||
// KRResourceManager.cpp
|
||||
// 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
|
||||
// permitted provided that the following conditions are met:
|
||||
@@ -29,6 +29,15 @@
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
|
||||
void main() {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
#include "KRResourceManager.h"
|
||||
#include "KREngine-common.h"
|
||||
|
||||
KRResourceManager::KRResourceManager(KRContext &context) : KRContextObject(context)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
KRResourceManager::~KRResourceManager()
|
||||
{
|
||||
|
||||
}
|
||||
33
kraken_standard_assets_ios/Shaders/sky_box.vsh → kraken/KRResourceManager.h
Executable file → Normal file
33
kraken_standard_assets_ios/Shaders/sky_box.vsh → kraken/KRResourceManager.h
Executable file → Normal file
@@ -1,7 +1,8 @@
|
||||
//
|
||||
// sky_box.vsh
|
||||
// KRResourceManager.h
|
||||
// KREngine
|
||||
//
|
||||
//
|
||||
// Copyright 2012 Kearwood Gilbert. All rights reserved.
|
||||
//
|
||||
// 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
|
||||
// or implied, of Kearwood Gilbert.
|
||||
//
|
||||
//
|
||||
|
||||
attribute vec4 vertex_position;
|
||||
//attribute lowp vec4 vertex_uv;
|
||||
//
|
||||
//varying mediump vec2 textureCoordinate;
|
||||
#ifndef KRRESOURCEMANAGER_H
|
||||
#define KRRESOURCEMANAGER_H
|
||||
#include "KREngine-common.h"
|
||||
|
||||
varying mediump vec3 texCoord;
|
||||
uniform highp mat4 inv_mvp_matrix_no_translate; // Inverse of the model-view-projection matrix, without view translation component
|
||||
uniform mediump vec4 viewport;
|
||||
#include "KRResource.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(vertex_position.xy, 1.0, 1.0);
|
||||
class KRResourceManager : public KRContextObject {
|
||||
public:
|
||||
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);
|
||||
t *= 1.0 / t.w;
|
||||
texCoord = vec3(t);
|
||||
}
|
||||
#endif // KRRESOURCEMANAGER_H
|
||||
@@ -1,166 +1,166 @@
|
||||
//
|
||||
// KRReverbZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRReverbZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_reverb = "";
|
||||
m_reverb_gain = 1.0f;
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRReverbZone::~KRReverbZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getElementName() {
|
||||
return "reverb_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_reverb.c_str());
|
||||
e->SetAttribute("gain", m_reverb_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_reverb = e->Attribute("sample");
|
||||
|
||||
m_reverb_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_reverb_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getReverb()
|
||||
{
|
||||
return m_reverb;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverb(const std::string &reverb)
|
||||
{
|
||||
m_reverb = reverb;
|
||||
}
|
||||
|
||||
float KRReverbZone::getReverbGain()
|
||||
{
|
||||
return m_reverb_gain;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverbGain(float reverb_gain)
|
||||
{
|
||||
m_reverb_gain = reverb_gain;
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRReverbZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
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);
|
||||
|
||||
if(getContext().getShaderManager()->selectShader(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRReverbZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRReverbZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRReverbZone::getBounds() {
|
||||
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRReverbZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
//
|
||||
// KRReverbZone.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-12-06.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRReverbZone.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRReverbZone::KRReverbZone(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_reverb = "";
|
||||
m_reverb_gain = 1.0f;
|
||||
m_gradient_distance = 0.25f;
|
||||
|
||||
}
|
||||
|
||||
KRReverbZone::~KRReverbZone()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getElementName() {
|
||||
return "reverb_zone";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRReverbZone::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("zone", m_zone.c_str());
|
||||
e->SetAttribute("sample", m_reverb.c_str());
|
||||
e->SetAttribute("gain", m_reverb_gain);
|
||||
e->SetAttribute("gradient", m_gradient_distance);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRReverbZone::loadXML(tinyxml2::XMLElement *e)
|
||||
{
|
||||
KRNode::loadXML(e);
|
||||
|
||||
m_zone = e->Attribute("zone");
|
||||
|
||||
m_gradient_distance = 0.25f;
|
||||
if(e->QueryFloatAttribute("gradient", &m_gradient_distance) != tinyxml2::XML_SUCCESS) {
|
||||
m_gradient_distance = 0.25f;
|
||||
}
|
||||
|
||||
m_reverb = e->Attribute("sample");
|
||||
|
||||
m_reverb_gain = 1.0f;
|
||||
if(e->QueryFloatAttribute("gain", &m_reverb_gain) != tinyxml2::XML_SUCCESS) {
|
||||
m_reverb_gain = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getReverb()
|
||||
{
|
||||
return m_reverb;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverb(const std::string &reverb)
|
||||
{
|
||||
m_reverb = reverb;
|
||||
}
|
||||
|
||||
float KRReverbZone::getReverbGain()
|
||||
{
|
||||
return m_reverb_gain;
|
||||
}
|
||||
|
||||
void KRReverbZone::setReverbGain(float reverb_gain)
|
||||
{
|
||||
m_reverb_gain = reverb_gain;
|
||||
}
|
||||
|
||||
std::string KRReverbZone::getZone()
|
||||
{
|
||||
return m_zone;
|
||||
}
|
||||
|
||||
void KRReverbZone::setZone(const std::string &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)
|
||||
{
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
bool bVisualize = pCamera->settings.debug_display == KRRenderSettings::KRENGINE_DEBUG_DISPLAY_SIREN_REVERB_ZONES;
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_FORWARD_TRANSPARENT && bVisualize) {
|
||||
Matrix4 sphereModelMatrix = getModelMatrix();
|
||||
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, sphereModelMatrix, point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
std::vector<KRMesh *> sphereModels = getContext().getMeshManager()->getModel("__sphere");
|
||||
if(sphereModels.size()) {
|
||||
for(int i=0; i < sphereModels[0]->getSubmeshCount(); i++) {
|
||||
sphereModels[0]->renderSubmesh(i, renderPass, getName(), "visualize_overlay", 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable alpha blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float KRReverbZone::getGradientDistance()
|
||||
{
|
||||
return m_gradient_distance;
|
||||
}
|
||||
|
||||
void KRReverbZone::setGradientDistance(float gradient_distance)
|
||||
{
|
||||
m_gradient_distance = gradient_distance;
|
||||
}
|
||||
|
||||
AABB KRReverbZone::getBounds() {
|
||||
// Reverb zones always have a -1, -1, -1 to 1, 1, 1 bounding box
|
||||
return AABB::Create(-Vector3::One(), Vector3::One(), getModelMatrix());
|
||||
}
|
||||
|
||||
float KRReverbZone::getContainment(const Vector3 &pos)
|
||||
{
|
||||
AABB bounds = getBounds();
|
||||
if(bounds.contains(pos)) {
|
||||
Vector3 size = bounds.size();
|
||||
Vector3 diff = pos - bounds.center();
|
||||
diff = diff * 2.0f;
|
||||
diff = Vector3::Create(diff.x / size.x, diff.y / size.y, diff.z / size.z);
|
||||
float d = diff.magnitude();
|
||||
|
||||
if(m_gradient_distance <= 0.0f) {
|
||||
// Avoid division by zero
|
||||
d = d > 1.0f ? 0.0f : 1.0f;
|
||||
} else {
|
||||
d = (1.0f - d) / m_gradient_distance;
|
||||
d = KRCLAMP(d, 0.0f, 1.0f);
|
||||
}
|
||||
return d;
|
||||
|
||||
} else {
|
||||
return 0.0f;
|
||||
}
|
||||
}
|
||||
1216
kraken/KRScene.cpp
1216
kraken/KRScene.cpp
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,7 @@
|
||||
#include "KRSceneManager.h"
|
||||
#include "KRScene.h"
|
||||
|
||||
KRSceneManager::KRSceneManager(KRContext &context) : KRContextObject(context){
|
||||
KRSceneManager::KRSceneManager(KRContext &context) : KRResourceManager(context){
|
||||
}
|
||||
|
||||
KRSceneManager::~KRSceneManager() {
|
||||
@@ -42,6 +42,21 @@ KRSceneManager::~KRSceneManager() {
|
||||
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) {
|
||||
std::string lowerName = name;
|
||||
std::transform(lowerName.begin(), lowerName.end(),
|
||||
|
||||
@@ -33,17 +33,22 @@
|
||||
#define KRENGINE_KRSCENEMANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
class KRScene;
|
||||
|
||||
|
||||
class KRSceneManager : public KRContextObject {
|
||||
class KRSceneManager : public KRResourceManager {
|
||||
public:
|
||||
KRSceneManager(KRContext &context);
|
||||
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);
|
||||
KRScene *loadScene(const std::string &name, KRDataBlock *data);
|
||||
|
||||
|
||||
661
kraken/KRShader.cpp
Executable file → Normal file
661
kraken/KRShader.cpp
Executable file → Normal file
@@ -1,596 +1,65 @@
|
||||
//
|
||||
// KRShader.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 "KRShader.h"
|
||||
#include "assert.h"
|
||||
#include "KRLight.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
const char *KRShader::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
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
//
|
||||
// KRShader.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 "KRShader.h"
|
||||
|
||||
KRShader::KRShader(KRContext &context, std::string name, std::string extension) : KRResource(context, name)
|
||||
{
|
||||
m_pData = new KRDataBlock();
|
||||
m_extension = extension;
|
||||
}
|
||||
|
||||
KRShader::KRShader(KRContext &context, std::string name, std::string extension, KRDataBlock *data) : KRResource(context, name)
|
||||
{
|
||||
m_pData = data;
|
||||
m_extension = extension;
|
||||
}
|
||||
|
||||
KRShader::~KRShader()
|
||||
{
|
||||
delete m_pData;
|
||||
}
|
||||
|
||||
std::string KRShader::getExtension()
|
||||
{
|
||||
return m_extension;
|
||||
}
|
||||
|
||||
bool KRShader::save(KRDataBlock &data)
|
||||
{
|
||||
data.append(*m_pData);
|
||||
return true;
|
||||
}
|
||||
|
||||
KRDataBlock *KRShader::getData()
|
||||
{
|
||||
return m_pData;
|
||||
}
|
||||
|
||||
144
kraken/KRShader.h
Executable file → Normal file
144
kraken/KRShader.h
Executable file → Normal file
@@ -2,18 +2,18 @@
|
||||
// KRShader.h
|
||||
// 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
|
||||
// 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
|
||||
@@ -23,139 +23,37 @@
|
||||
// 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 KRSHADER_H
|
||||
#define KRSHADER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRNode.h"
|
||||
#include "KRViewport.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRResource.h"
|
||||
|
||||
class KRShader : public KRContextObject {
|
||||
class KRShader : public KRResource {
|
||||
|
||||
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();
|
||||
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 {
|
||||
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);
|
||||
virtual bool save(KRDataBlock &data);
|
||||
|
||||
KRDataBlock *getData();
|
||||
|
||||
private:
|
||||
GLuint m_iProgram;
|
||||
|
||||
std::string m_extension;
|
||||
KRDataBlock *m_pData;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif /* defined(KRSHADER_H) */
|
||||
|
||||
320
kraken/KRShaderManager.cpp
Executable file → Normal file
320
kraken/KRShaderManager.cpp
Executable file → Normal file
@@ -1,19 +1,19 @@
|
||||
//
|
||||
// KRShaderManager.cpp
|
||||
// ShaderManager.cpp
|
||||
// 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
|
||||
// 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
|
||||
@@ -23,261 +23,95 @@
|
||||
// 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 "KRShaderManager.h"
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#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)
|
||||
KRShaderManager::KRShaderManager(KRContext &context) : KRResourceManager(context)
|
||||
{
|
||||
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) {
|
||||
return pShader->bind(camera, viewport, matModel, point_lights, directional_lights, spot_lights, renderPass, rim_color, rim_power, fade_color);
|
||||
for(unordered_map<std::string, unordered_map<std::string, KRShader *> >::iterator extension_itr = m_shaders.begin(); extension_itr != m_shaders.end(); extension_itr++) {
|
||||
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 {
|
||||
return false;
|
||||
(*extension_itr).second[lower_name] = shader;
|
||||
}
|
||||
}
|
||||
|
||||
void KRShaderManager::loadFragmentShader(const std::string &name, KRDataBlock *data) {
|
||||
m_fragShaderSource[name] = data->getString();
|
||||
delete data;
|
||||
KRShader *KRShaderManager::load(const std::string &name, const std::string &extension, KRDataBlock *data)
|
||||
{
|
||||
KRShader *shader = new KRShader(getContext(), name, extension, data);
|
||||
if(shader) add(shader);
|
||||
return shader;
|
||||
}
|
||||
|
||||
void KRShaderManager::loadVertexShader(const std::string &name, KRDataBlock *data) {
|
||||
m_vertShaderSource[name] = data->getString();
|
||||
delete data;
|
||||
KRShader *KRShaderManager::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_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
70
kraken/KRShaderManager.h
Executable file → Normal file
@@ -1,19 +1,19 @@
|
||||
//
|
||||
// KRShaderManager.h
|
||||
// ShaderManager.h
|
||||
// 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
|
||||
// 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
|
||||
@@ -23,57 +23,43 @@
|
||||
// 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 KRSHADER_MANAGER_H
|
||||
#define KRSHADER_MANAGER_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRCamera.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRNode.h"
|
||||
|
||||
using std::map;
|
||||
using std::vector;
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRShader.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
|
||||
#ifndef KRSHADERMANAGER_H
|
||||
#define KRSHADERMANAGER_H
|
||||
|
||||
class KRShader;
|
||||
class KRCamera;
|
||||
|
||||
class KRShaderManager : public KRContextObject {
|
||||
class KRShaderManager : public KRResourceManager {
|
||||
public:
|
||||
KRShaderManager(KRContext &context);
|
||||
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:
|
||||
//unordered_map<std::string, KRShader *> m_shaders;
|
||||
std::map<std::pair<std::string, std::vector<int> >, KRShader *> m_shaders;
|
||||
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, std::string> m_fragShaderSource;
|
||||
unordered_map<std::string, std::string> m_vertShaderSource;
|
||||
void add(KRShader *shader);
|
||||
|
||||
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
65
kraken/KRSource.cpp
Normal 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;
|
||||
}
|
||||
102
kraken_standard_assets_ios/Shaders/dust_particle.fsh → kraken/KRSource.h
Executable file → Normal file
102
kraken_standard_assets_ios/Shaders/dust_particle.fsh → kraken/KRSource.h
Executable file → Normal file
@@ -1,43 +1,59 @@
|
||||
//
|
||||
// dust_particle.fsh
|
||||
// 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.
|
||||
//
|
||||
|
||||
#extension GL_EXT_shadow_samplers : require
|
||||
|
||||
varying mediump vec2 texCoord;
|
||||
|
||||
varying mediump vec4 shadowMapCoord1;
|
||||
uniform sampler2DShadow shadowTexture1;
|
||||
uniform mediump vec3 light_color;
|
||||
varying lowp float intensity_modulate;
|
||||
|
||||
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;
|
||||
}
|
||||
//
|
||||
// KRSource.h
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef KRSOURCE_H
|
||||
#define KRSOURCE_H
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KRDataBlock.h"
|
||||
#include "KRResource.h"
|
||||
|
||||
class KRSource : public KRResource {
|
||||
|
||||
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
148
kraken/KRSourceManager.cpp
Normal 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
63
kraken/KRSourceManager.h
Normal 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) */
|
||||
@@ -1,61 +1,61 @@
|
||||
//
|
||||
// KRSpotLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSpotLight.h"
|
||||
|
||||
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
}
|
||||
|
||||
KRSpotLight::~KRSpotLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRSpotLight::getElementName() {
|
||||
return "spot_light";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
||||
e->SetAttribute("inner_angle", m_innerAngle);
|
||||
e->SetAttribute("outer_angle", m_outerAngle);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRLight::loadXML(e);
|
||||
|
||||
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
||||
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
||||
}
|
||||
|
||||
float KRSpotLight::getInnerAngle() {
|
||||
return m_innerAngle;
|
||||
}
|
||||
float KRSpotLight::getOuterAngle() {
|
||||
return m_outerAngle;
|
||||
}
|
||||
void KRSpotLight::setInnerAngle(float innerAngle) {
|
||||
m_innerAngle = innerAngle;
|
||||
}
|
||||
void KRSpotLight::setOuterAngle(float outerAngle) {
|
||||
m_outerAngle = outerAngle;
|
||||
}
|
||||
|
||||
AABB KRSpotLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// KRSpotLight.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSpotLight.h"
|
||||
|
||||
KRSpotLight::KRSpotLight(KRScene &scene, std::string name) : KRLight(scene, name)
|
||||
{
|
||||
}
|
||||
|
||||
KRSpotLight::~KRSpotLight()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string KRSpotLight::getElementName() {
|
||||
return "spot_light";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSpotLight::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRLight::saveXML(parent);
|
||||
e->SetAttribute("inner_angle", m_innerAngle);
|
||||
e->SetAttribute("outer_angle", m_outerAngle);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSpotLight::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRLight::loadXML(e);
|
||||
|
||||
e->QueryFloatAttribute("inner_angle", &m_innerAngle);
|
||||
e->QueryFloatAttribute("outer_angle", &m_outerAngle);
|
||||
}
|
||||
|
||||
float KRSpotLight::getInnerAngle() {
|
||||
return m_innerAngle;
|
||||
}
|
||||
float KRSpotLight::getOuterAngle() {
|
||||
return m_outerAngle;
|
||||
}
|
||||
void KRSpotLight::setInnerAngle(float innerAngle) {
|
||||
m_innerAngle = innerAngle;
|
||||
}
|
||||
void KRSpotLight::setOuterAngle(float outerAngle) {
|
||||
m_outerAngle = outerAngle;
|
||||
}
|
||||
|
||||
AABB KRSpotLight::getBounds() {
|
||||
float influence_radius = m_decayStart - sqrt(m_intensity * 0.01f) / sqrt(KRLIGHT_MIN_INFLUENCE);
|
||||
if(influence_radius < m_flareOcclusionSize) {
|
||||
influence_radius = m_flareOcclusionSize;
|
||||
}
|
||||
return AABB::Create(Vector3::Create(-influence_radius), Vector3::Create(influence_radius), getModelMatrix());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,141 +1,141 @@
|
||||
//
|
||||
// KRSprite.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSprite.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRShaderManager.h"
|
||||
#include "KRShader.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_spriteTexture = "";
|
||||
m_pSpriteTexture = NULL;
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
KRSprite::~KRSprite()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRSprite::getElementName() {
|
||||
return "sprite";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
||||
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
||||
if(szSpriteTexture) {
|
||||
m_spriteTexture = szSpriteTexture;
|
||||
} else {
|
||||
m_spriteTexture = "";
|
||||
}
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
||||
m_spriteTexture = sprite_texture;
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteAlpha(float alpha)
|
||||
{
|
||||
m_spriteAlpha = alpha;
|
||||
}
|
||||
|
||||
float KRSprite::getSpriteAlpha() const
|
||||
{
|
||||
return m_spriteAlpha;
|
||||
}
|
||||
|
||||
AABB KRSprite::getBounds() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
// Pre-stream sprites, even if the alpha is zero
|
||||
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
||||
|
||||
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
/*
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
*/
|
||||
|
||||
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// 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);
|
||||
if(getContext().getShaderManager()->selectShader(*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);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRSprite.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 12-04-05.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
|
||||
#include "KREngine-common.h"
|
||||
#include "KRSprite.h"
|
||||
|
||||
#include "KRNode.h"
|
||||
#include "KRCamera.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include "KRPipelineManager.h"
|
||||
#include "KRPipeline.h"
|
||||
#include "KRStockGeometry.h"
|
||||
#include "KRDirectionalLight.h"
|
||||
#include "KRSpotLight.h"
|
||||
#include "KRPointLight.h"
|
||||
|
||||
|
||||
KRSprite::KRSprite(KRScene &scene, std::string name) : KRNode(scene, name)
|
||||
{
|
||||
m_spriteTexture = "";
|
||||
m_pSpriteTexture = NULL;
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
KRSprite::~KRSprite()
|
||||
{
|
||||
}
|
||||
|
||||
std::string KRSprite::getElementName() {
|
||||
return "sprite";
|
||||
}
|
||||
|
||||
tinyxml2::XMLElement *KRSprite::saveXML( tinyxml2::XMLNode *parent)
|
||||
{
|
||||
tinyxml2::XMLElement *e = KRNode::saveXML(parent);
|
||||
e->SetAttribute("sprite_texture", m_spriteTexture.c_str());
|
||||
e->SetAttribute("sprite_alpha", m_spriteAlpha);
|
||||
return e;
|
||||
}
|
||||
|
||||
void KRSprite::loadXML(tinyxml2::XMLElement *e) {
|
||||
KRNode::loadXML(e);
|
||||
|
||||
if(e->QueryFloatAttribute("sprite_alpha", &m_spriteAlpha) != tinyxml2::XML_SUCCESS) {
|
||||
m_spriteAlpha = 1.0f;
|
||||
}
|
||||
|
||||
const char *szSpriteTexture = e->Attribute("sprite_texture");
|
||||
if(szSpriteTexture) {
|
||||
m_spriteTexture = szSpriteTexture;
|
||||
} else {
|
||||
m_spriteTexture = "";
|
||||
}
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteTexture(std::string sprite_texture) {
|
||||
m_spriteTexture = sprite_texture;
|
||||
m_pSpriteTexture = NULL;
|
||||
}
|
||||
|
||||
void KRSprite::setSpriteAlpha(float alpha)
|
||||
{
|
||||
m_spriteAlpha = alpha;
|
||||
}
|
||||
|
||||
float KRSprite::getSpriteAlpha() const
|
||||
{
|
||||
return m_spriteAlpha;
|
||||
}
|
||||
|
||||
AABB KRSprite::getBounds() {
|
||||
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) {
|
||||
|
||||
if(m_lod_visible >= LOD_VISIBILITY_PRESTREAM && renderPass == KRNode::RENDER_PASS_PRESTREAM) {
|
||||
// Pre-stream sprites, even if the alpha is zero
|
||||
if(m_spriteTexture.size() && m_pSpriteTexture == NULL) {
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
m_pSpriteTexture->resetPoolExpiry(0.0f, KRTexture::TEXTURE_USAGE_SPRITE);
|
||||
}
|
||||
}
|
||||
|
||||
if(m_lod_visible <= LOD_VISIBILITY_PRESTREAM) return;
|
||||
|
||||
KRNode::render(pCamera, point_lights, directional_lights, spot_lights, viewport, renderPass);
|
||||
|
||||
|
||||
if(renderPass == KRNode::RENDER_PASS_ADDITIVE_PARTICLES) {
|
||||
if(m_spriteTexture.size() && m_spriteAlpha > 0.0f) {
|
||||
|
||||
|
||||
if(!m_pSpriteTexture && m_spriteTexture.size()) {
|
||||
m_pSpriteTexture = getContext().getTextureManager()->getTexture(m_spriteTexture);
|
||||
}
|
||||
|
||||
if(m_pSpriteTexture) {
|
||||
/*
|
||||
// Enable additive blending
|
||||
GLDEBUG(glEnable(GL_BLEND));
|
||||
GLDEBUG(glBlendFunc(GL_ONE, GL_ONE));
|
||||
|
||||
// Disable z-buffer write
|
||||
GLDEBUG(glDepthMask(GL_FALSE));
|
||||
*/
|
||||
|
||||
// TODO - Sprites are currently additive only. Need to expose this and allow for multiple blending modes
|
||||
|
||||
// Enable z-buffer test
|
||||
GLDEBUG(glEnable(GL_DEPTH_TEST));
|
||||
GLDEBUG(glDepthFunc(GL_LEQUAL));
|
||||
GLDEBUG(glDepthRangef(0.0, 1.0));
|
||||
|
||||
// Render light sprite on transparency pass
|
||||
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().getPipelineManager()->selectPipeline(*pCamera, pShader, viewport, getModelMatrix(), point_lights, directional_lights, spot_lights, 0, renderPass, Vector3::Zero(), 0.0f, Vector4::Zero())) {
|
||||
pShader->setUniform(KRPipeline::KRENGINE_UNIFORM_MATERIAL_ALPHA, m_spriteAlpha);
|
||||
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);
|
||||
GLDEBUG(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +1,62 @@
|
||||
//
|
||||
// KRStreamer.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 11/1/2013.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRStreamer.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
||||
KRStreamer::KRStreamer(KRContext &context) : m_context(context)
|
||||
{
|
||||
m_running = false;
|
||||
m_stop = false;
|
||||
}
|
||||
|
||||
void KRStreamer::startStreamer()
|
||||
{
|
||||
if(!m_running) {
|
||||
m_running = true;
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
m_thread = std::thread(&KRStreamer::run, this);
|
||||
}
|
||||
}
|
||||
|
||||
KRStreamer::~KRStreamer()
|
||||
{
|
||||
if(m_running) {
|
||||
m_stop = true;
|
||||
m_thread.join();
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
void KRStreamer::run()
|
||||
{
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
// TODO - Set thread names on windows
|
||||
#else
|
||||
pthread_setname_np("Kraken - Streamer");
|
||||
#endif
|
||||
|
||||
std::chrono::microseconds sleep_duration( 15000 );
|
||||
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
m_context.doStreaming();
|
||||
std::this_thread::sleep_for( sleep_duration );
|
||||
}
|
||||
}
|
||||
//
|
||||
// KRStreamer.cpp
|
||||
// Kraken
|
||||
//
|
||||
// Created by Kearwood Gilbert on 11/1/2013.
|
||||
// Copyright (c) 2013 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRStreamer.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
||||
KRStreamer::KRStreamer(KRContext &context) : m_context(context)
|
||||
{
|
||||
m_running = false;
|
||||
m_stop = false;
|
||||
}
|
||||
|
||||
void KRStreamer::startStreamer()
|
||||
{
|
||||
if(!m_running) {
|
||||
m_running = true;
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
m_thread = std::thread(&KRStreamer::run, this);
|
||||
}
|
||||
}
|
||||
|
||||
KRStreamer::~KRStreamer()
|
||||
{
|
||||
if(m_running) {
|
||||
m_stop = true;
|
||||
m_thread.join();
|
||||
m_running = false;
|
||||
}
|
||||
}
|
||||
|
||||
void KRStreamer::run()
|
||||
{
|
||||
|
||||
#if defined(ANDROID)
|
||||
// TODO - Set thread names on Android
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
// TODO - Set thread names on windows
|
||||
#else
|
||||
pthread_setname_np("Kraken - Streamer");
|
||||
#endif
|
||||
|
||||
std::chrono::microseconds sleep_duration( 15000 );
|
||||
|
||||
KRContext::activateStreamerContext();
|
||||
|
||||
while(!m_stop)
|
||||
{
|
||||
m_context.doStreaming();
|
||||
std::this_thread::sleep_for( sleep_duration );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ void KRTexture::resize(int max_dim)
|
||||
m_iNewHandle = 0;
|
||||
} else {
|
||||
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)) {
|
||||
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) {
|
||||
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;
|
||||
} 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;
|
||||
} else {
|
||||
return kraken_stream_level::STREAM_LEVEL_OUT;
|
||||
|
||||
@@ -43,13 +43,13 @@ KRTextureAnimated::KRTextureAnimated(KRContext &context, std::string name) : KRT
|
||||
// - yy is the framerate
|
||||
|
||||
// TODO - Add error handling for mal-formatted animated texture formats
|
||||
int first_comma_pos = name.find(",");
|
||||
int second_comma_pos = name.find(",", first_comma_pos + 1);
|
||||
size_t first_comma_pos = name.find(",");
|
||||
size_t second_comma_pos = name.find(",", first_comma_pos + 1);
|
||||
|
||||
|
||||
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_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_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++) {
|
||||
KRTexture2D *frame_texture = textureForFrame(i);
|
||||
if(frame_texture) {
|
||||
if(frame_texture->getMaxMipMap() < 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->getMaxMipMap() < (int)m_max_lod_max_dim) m_max_lod_max_dim = frame_texture->getMaxMipMap();
|
||||
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?
|
||||
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);
|
||||
if(frame_texture) {
|
||||
frame_texture->bind(texture_unit);
|
||||
|
||||
@@ -44,8 +44,8 @@ KRTextureCube::KRTextureCube(KRContext &context, std::string name) : KRTexture(c
|
||||
std::string faceName = getName() + SUFFIXES[i];
|
||||
m_textures[i] = (KRTexture2D *)getContext().getTextureManager()->getTexture(faceName);
|
||||
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]->getMinMipMap() > m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap();
|
||||
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() > (int)m_min_lod_max_dim) m_min_lod_max_dim = m_textures[i]->getMinMipMap();
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ bool KRTextureCube::createGLTexture(int lod_max_dim)
|
||||
long KRTextureCube::getMemRequiredForSize(int 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;
|
||||
for(int i=0; i<6; i++) {
|
||||
|
||||
@@ -59,7 +59,7 @@ KRTextureKTX::KRTextureKTX(KRContext &context, KRDataBlock *data, std::string na
|
||||
uint32_t blockStart = sizeof(KTXHeader) + m_header.bytesOfKeyValueData;
|
||||
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;
|
||||
data->copy(&blockLength, blockStart, 4);
|
||||
blockStart += 4;
|
||||
@@ -126,7 +126,7 @@ KRTextureKTX::~KRTextureKTX() {
|
||||
long KRTextureKTX::getMemRequiredForSize(int 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
|
||||
|
||||
@@ -137,7 +137,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
|
||||
for(std::list<KRDataBlock *>::iterator itr = m_blocks.begin(); itr != m_blocks.end(); itr++) {
|
||||
KRDataBlock *block = *itr;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
memoryRequired += block->getSize();
|
||||
memoryRequired += (long)block->getSize();
|
||||
}
|
||||
|
||||
width = width >> 1;
|
||||
@@ -156,7 +156,7 @@ long KRTextureKTX::getMemRequiredForSize(int max_dim)
|
||||
bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
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) {
|
||||
return false;
|
||||
@@ -239,9 +239,9 @@ bool KRTextureKTX::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
GLDEBUG(glCompressedTexImage2D(target, destination_level, (GLenum)m_header.glInternalFormat, width, height, 0, (GLsizei)block->getSize(), block->getStart()));
|
||||
#endif
|
||||
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
|
||||
memoryRequired += block->getSize();
|
||||
memoryRequired += (long)block->getSize();
|
||||
//
|
||||
// err = glGetError();
|
||||
// if (err != GL_NO_ERROR) {
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "KRTextureAnimated.h"
|
||||
#include "KRContext.h"
|
||||
|
||||
KRTextureManager::KRTextureManager(KRContext &context) : KRContextObject(context) {
|
||||
KRTextureManager::KRTextureManager(KRContext &context) : KRResourceManager(context) {
|
||||
m_textureMemUsed = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
#if !defined(ANDROID)
|
||||
if(m_maxAnisotropy[i] != max_anisotropy) {
|
||||
_setActiveTexture(i);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_anisotropy);
|
||||
m_maxAnisotropy[i] = max_anisotropy;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
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 *pTexture = NULL;
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#include "KREngine-common.h"
|
||||
|
||||
#include "KRResourceManager.h"
|
||||
|
||||
#include "KRTexture.h"
|
||||
#include "KRContextObject.h"
|
||||
#include "KREngine-common.h"
|
||||
@@ -41,10 +43,13 @@
|
||||
#include "KRContext.h"
|
||||
#include "KRStreamer.h"
|
||||
|
||||
class KRTextureManager : public KRContextObject {
|
||||
class KRTextureManager : public KRResourceManager {
|
||||
public:
|
||||
KRTextureManager(KRContext &context);
|
||||
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);
|
||||
bool selectTexture(GLenum target, int iTextureUnit, int iTextureHandle);
|
||||
|
||||
@@ -147,7 +147,7 @@ KRTexturePVR::~KRTexturePVR() {
|
||||
long KRTexturePVR::getMemRequiredForSize(int 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
|
||||
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++) {
|
||||
KRDataBlock *block = *itr;
|
||||
if(width <= target_dim && height <= target_dim) {
|
||||
memoryRequired += block->getSize();
|
||||
memoryRequired += (long)block->getSize();
|
||||
}
|
||||
|
||||
width = width >> 1;
|
||||
@@ -176,7 +176,7 @@ long KRTexturePVR::getMemRequiredForSize(int max_dim)
|
||||
bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
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) {
|
||||
return false;
|
||||
@@ -256,12 +256,12 @@ bool KRTexturePVR::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lo
|
||||
#if GL_EXT_texture_storage
|
||||
GLDEBUG(glCompressedTexSubImage2D(target, destination_level, 0, 0, width, height, m_internalFormat, block->getSize(), block->getStart()));
|
||||
#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
|
||||
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
|
||||
memoryRequired += block->getSize();
|
||||
memoryRequired += (long)block->getSize();
|
||||
//
|
||||
// err = glGetError();
|
||||
// if (err != GL_NO_ERROR) {
|
||||
|
||||
@@ -1,385 +1,399 @@
|
||||
//
|
||||
// KRTextureTGA.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-23.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRTextureTGA.h"
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRTextureKTX.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} TGA_HEADER;
|
||||
#pragma pack()
|
||||
#else
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} __attribute__((packed)) TGA_HEADER;
|
||||
#endif
|
||||
|
||||
|
||||
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
||||
{
|
||||
data->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
||||
|
||||
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
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->unlock();
|
||||
}
|
||||
|
||||
KRTextureTGA::~KRTextureTGA()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
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);
|
||||
|
||||
GLenum internal_format = GL_RGBA;
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
if(compress) {
|
||||
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(pHeader->colourmaptype != 0) {
|
||||
m_pData->unlock();
|
||||
return false; // Mapped colors not supported
|
||||
}
|
||||
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
//#ifdef __APPLE__
|
||||
// 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 };
|
||||
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
||||
//#else
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
//#endif
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
if(premultiply_alpha) {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
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(glFinish());
|
||||
free(converted_image);
|
||||
} else {
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
||||
GLDEBUG(glFinish());
|
||||
}
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 32:
|
||||
{
|
||||
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;
|
||||
if(premultiply_alpha) {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__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++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = (__uint32_t)pSource[0] * (__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++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
} else {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
}
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
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;
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = 0xff;
|
||||
}
|
||||
pSource += 3;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // Image type not yet supported
|
||||
}
|
||||
|
||||
m_pData->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
|
||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
|
||||
std::list<KRDataBlock *> blocks;
|
||||
|
||||
getContext().getTextureManager()->_setActiveTexture(0);
|
||||
|
||||
GLuint compressed_handle = 0;
|
||||
GLDEBUG(glGenTextures(1, &compressed_handle));
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||
|
||||
int current_max_dim = 0;
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
||||
assert(false); // Failed to upload the texture
|
||||
}
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
|
||||
GLint width = 0, height = 0, internal_format, base_internal_format;
|
||||
|
||||
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
||||
|
||||
/*
|
||||
int texture_base_level = 0;
|
||||
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));
|
||||
*/
|
||||
switch(internal_format)
|
||||
{
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
default:
|
||||
assert(false); // Not yet supported
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint lod_level = 0;
|
||||
GLint compressed_size = 0;
|
||||
int lod_width = width;
|
||||
while(lod_width > 1) {
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
||||
KRDataBlock *new_block = new KRDataBlock();
|
||||
new_block->expand(compressed_size);
|
||||
new_block->lock();
|
||||
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
||||
new_block->unlock();
|
||||
blocks.push_back(new_block);
|
||||
|
||||
lod_level++;
|
||||
}
|
||||
assert(lod_width == 1);
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
||||
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
||||
|
||||
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
||||
|
||||
m_pData->unlock();
|
||||
|
||||
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
||||
KRDataBlock *block = *block_itr;
|
||||
delete block;
|
||||
}
|
||||
|
||||
return new_texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||
{
|
||||
return m_imageSize;
|
||||
}
|
||||
|
||||
std::string KRTextureTGA::getExtension()
|
||||
{
|
||||
return "tga";
|
||||
}
|
||||
//
|
||||
// KRTextureTGA.cpp
|
||||
// KREngine
|
||||
//
|
||||
// Created by Kearwood Gilbert on 2012-10-23.
|
||||
// Copyright (c) 2012 Kearwood Software. All rights reserved.
|
||||
//
|
||||
|
||||
#include "KRTextureTGA.h"
|
||||
#include "KREngine-common.h"
|
||||
#include "KRContext.h"
|
||||
#include "KRTextureKTX.h"
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#pragma pack(1)
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} TGA_HEADER;
|
||||
#pragma pack()
|
||||
#else
|
||||
typedef struct {
|
||||
char idlength;
|
||||
char colourmaptype;
|
||||
char imagetype;
|
||||
short int colourmaporigin;
|
||||
short int colourmaplength;
|
||||
char colourmapdepth;
|
||||
short int x_origin;
|
||||
short int y_origin;
|
||||
short width;
|
||||
short height;
|
||||
char bitsperpixel;
|
||||
char imagedescriptor;
|
||||
} __attribute__((packed)) TGA_HEADER;
|
||||
#endif
|
||||
|
||||
|
||||
KRTextureTGA::KRTextureTGA(KRContext &context, KRDataBlock *data, std::string name) : KRTexture2D(context, data, name)
|
||||
{
|
||||
data->lock();
|
||||
TGA_HEADER *pHeader = (TGA_HEADER *)data->getStart();
|
||||
|
||||
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
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
m_imageSize = pHeader->width * pHeader->height * 4;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
data->unlock();
|
||||
}
|
||||
|
||||
KRTextureTGA::~KRTextureTGA()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool KRTextureTGA::uploadTexture(GLenum target, int lod_max_dim, int ¤t_lod_max_dim, bool compress, bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
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);
|
||||
|
||||
GLenum internal_format = GL_RGBA;
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
if(compress) {
|
||||
internal_format = pHeader->bitsperpixel == 24 ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(pHeader->colourmaptype != 0) {
|
||||
m_pData->unlock();
|
||||
return false; // Mapped colors not supported
|
||||
}
|
||||
|
||||
switch(pHeader->imagetype) {
|
||||
case 2: // rgb
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 24:
|
||||
{
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
//#ifdef __APPLE__
|
||||
// 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 };
|
||||
// vImageConvert_RGB888toRGBA8888(&source_image, NULL, 0xff, &dest_image, false, kvImageDoNotTile);
|
||||
//#else
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
//#endif
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
{
|
||||
if(premultiply_alpha) {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*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];
|
||||
pSource += 4;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
} else {
|
||||
unsigned char *converted_image = (unsigned char *)malloc(pHeader->width * pHeader->height * 4);
|
||||
|
||||
unsigned char *pSource = pData;
|
||||
unsigned char *pDest = converted_image;
|
||||
unsigned char *pEnd = pData + pHeader->height * pHeader->width * 3;
|
||||
while(pSource < pEnd) {
|
||||
*pDest++ = (__uint32_t)pSource[2];
|
||||
*pDest++ = (__uint32_t)pSource[1];
|
||||
*pDest++ = (__uint32_t)pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)pData));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
}
|
||||
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
case 10: // rgb + rle
|
||||
switch(pHeader->bitsperpixel) {
|
||||
case 32:
|
||||
{
|
||||
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;
|
||||
if(premultiply_alpha) {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*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];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*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];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
} else {
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
}
|
||||
pSource += 4;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = pSource[3];
|
||||
pSource += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
}
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
{
|
||||
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;
|
||||
while(pDest < pEnd) {
|
||||
int count = (*pSource & 0x7f) + 1;
|
||||
if(*pSource & 0x80) {
|
||||
// RLE Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
}
|
||||
pSource += 3;
|
||||
} else {
|
||||
// RAW Packet
|
||||
pSource++;
|
||||
while(count--) {
|
||||
*pDest++ = pSource[2];
|
||||
*pDest++ = pSource[1];
|
||||
*pDest++ = pSource[0];
|
||||
*pDest++ = 0xff;
|
||||
pSource += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(pSource <= m_pData->getEnd());
|
||||
assert(pDest == pEnd);
|
||||
GLDEBUG(glTexImage2D(target, 0, internal_format, pHeader->width, pHeader->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)converted_image));
|
||||
GLDEBUG(glFinish());
|
||||
free(converted_image);
|
||||
current_lod_max_dim = m_max_lod_max_dim;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // 16-bit images not yet supported
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_pData->unlock();
|
||||
return false; // Image type not yet supported
|
||||
}
|
||||
|
||||
m_pData->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
#if !TARGET_OS_IPHONE && !defined(ANDROID)
|
||||
|
||||
KRTexture *KRTextureTGA::compress(bool premultiply_alpha)
|
||||
{
|
||||
m_pData->lock();
|
||||
|
||||
std::list<KRDataBlock *> blocks;
|
||||
|
||||
getContext().getTextureManager()->_setActiveTexture(0);
|
||||
|
||||
GLuint compressed_handle = 0;
|
||||
GLDEBUG(glGenTextures(1, &compressed_handle));
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, compressed_handle));
|
||||
|
||||
int current_max_dim = 0;
|
||||
if(!uploadTexture(GL_TEXTURE_2D, m_max_lod_max_dim, current_max_dim, true, premultiply_alpha)) {
|
||||
assert(false); // Failed to upload the texture
|
||||
}
|
||||
GLDEBUG(glGenerateMipmap(GL_TEXTURE_2D));
|
||||
|
||||
GLint width = 0, height = 0, internal_format, base_internal_format;
|
||||
|
||||
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &internal_format));
|
||||
|
||||
/*
|
||||
int texture_base_level = 0;
|
||||
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));
|
||||
*/
|
||||
switch(internal_format)
|
||||
{
|
||||
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
base_internal_format = GL_BGRA;
|
||||
break;
|
||||
default:
|
||||
assert(false); // Not yet supported
|
||||
break;
|
||||
}
|
||||
|
||||
GLuint lod_level = 0;
|
||||
GLint compressed_size = 0;
|
||||
int lod_width = width;
|
||||
while(lod_width > 1) {
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_WIDTH, &lod_width));
|
||||
GLDEBUG(glGetTexLevelParameteriv(GL_TEXTURE_2D, lod_level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &compressed_size));
|
||||
KRDataBlock *new_block = new KRDataBlock();
|
||||
new_block->expand(compressed_size);
|
||||
new_block->lock();
|
||||
GLDEBUG(glGetCompressedTexImage(GL_TEXTURE_2D, lod_level, new_block->getStart()));
|
||||
new_block->unlock();
|
||||
blocks.push_back(new_block);
|
||||
|
||||
lod_level++;
|
||||
}
|
||||
assert(lod_width == 1);
|
||||
|
||||
GLDEBUG(glBindTexture(GL_TEXTURE_2D, 0));
|
||||
getContext().getTextureManager()->selectTexture(0, NULL, 0.0f, KRTexture::TEXTURE_USAGE_NONE);
|
||||
GLDEBUG(glDeleteTextures(1, &compressed_handle));
|
||||
|
||||
KRTextureKTX *new_texture = new KRTextureKTX(getContext(), getName(), internal_format, base_internal_format, width, height, blocks);
|
||||
|
||||
m_pData->unlock();
|
||||
|
||||
for(auto block_itr = blocks.begin(); block_itr != blocks.end(); block_itr++) {
|
||||
KRDataBlock *block = *block_itr;
|
||||
delete block;
|
||||
}
|
||||
|
||||
return new_texture;
|
||||
}
|
||||
#endif
|
||||
|
||||
long KRTextureTGA::getMemRequiredForSize(int max_dim)
|
||||
{
|
||||
return m_imageSize;
|
||||
}
|
||||
|
||||
std::string KRTextureTGA::getExtension()
|
||||
{
|
||||
return "tga";
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
|
||||
bool uploadTexture(GLenum target, int lod_max_dim, int ¤t_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);
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user