Initial commit
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define OZZ_INCLUDE_PRIVATE_HEADER // Allows to include private headers.
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
#include "ozz/base/log.h"
|
||||
#include "ozz/base/maths/box.h"
|
||||
#include "ozz/base/maths/math_constant.h"
|
||||
#include "ozz/base/maths/math_ex.h"
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
#include "framework/application.h"
|
||||
#include "framework/imgui.h"
|
||||
|
||||
#include "renderer_impl.h"
|
||||
|
||||
using ozz::math::Float2;
|
||||
using ozz::math::Float3;
|
||||
using ozz::math::Float4x4;
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
// Declares camera navigation constants.
|
||||
const float kDefaultDistance = 8.f;
|
||||
const Float3 kDefaultCenter = Float3(0.f, .5f, 0.f);
|
||||
const Float2 kDefaultAngle =
|
||||
Float2(-ozz::math::kPi * 1.f / 12.f, ozz::math::kPi * 1.f / 5.f);
|
||||
const float kAngleFactor = .01f;
|
||||
const float kDistanceFactor = .1f;
|
||||
const float kScrollFactor = .03f;
|
||||
const float kPanFactor = .05f;
|
||||
const float kKeyboardFactor = 100.f;
|
||||
const float kNear = .01f;
|
||||
const float kFar = 1000.f;
|
||||
const float kFovY = ozz::math::kPi / 3.f;
|
||||
const float kFrameAllZoomOut = 1.3f; // 30% bigger than the scene.
|
||||
|
||||
// Setups initial values.
|
||||
Camera::Camera()
|
||||
: projection_(Float4x4::identity()),
|
||||
projection_2d_(Float4x4::identity()),
|
||||
view_(Float4x4::identity()),
|
||||
view_proj_(Float4x4::identity()),
|
||||
angles_(kDefaultAngle),
|
||||
center_(kDefaultCenter),
|
||||
distance_(kDefaultDistance),
|
||||
mouse_last_x_(0),
|
||||
mouse_last_y_(0),
|
||||
mouse_last_wheel_(0),
|
||||
auto_framing_(true) {}
|
||||
|
||||
Camera::~Camera() {}
|
||||
|
||||
void Camera::Update(const math::Box& _box, float _delta_time,
|
||||
bool _first_frame) {
|
||||
// Frame the scene according to the provided box.
|
||||
if (_box.is_valid()) {
|
||||
if (auto_framing_ || _first_frame) {
|
||||
center_ = (_box.max + _box.min) * .5f;
|
||||
if (_first_frame) {
|
||||
const float radius = Length(_box.max - _box.min) * .5f;
|
||||
distance_ = radius * kFrameAllZoomOut / tanf(kFovY * .5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update manual controls.
|
||||
const Controls controls = UpdateControls(_delta_time);
|
||||
|
||||
// Disable autoframing according to inputs.
|
||||
auto_framing_ &=
|
||||
!controls.panning && !controls.zooming && !controls.zooming_wheel;
|
||||
}
|
||||
|
||||
void Camera::Update(const math::Float4x4& _transform, const math::Box& _box,
|
||||
float _delta_time, bool _first_frame) {
|
||||
// Extract distance and angles such that theu are coherent when switching out
|
||||
// of auto_framing_.
|
||||
if (_box.is_valid()) {
|
||||
if (auto_framing_ || _first_frame) {
|
||||
// Extract components from the view martrix.
|
||||
ozz::math::Float3 camera_dir;
|
||||
ozz::math::Store3PtrU(-ozz::math::Normalize3(_transform.cols[2]),
|
||||
&camera_dir.x);
|
||||
ozz::math::Float3 camera_pos;
|
||||
ozz::math::Store3PtrU(_transform.cols[3], &camera_pos.x);
|
||||
|
||||
// Arbitrary decides that distance (focus point) is from camera to scene
|
||||
// center.
|
||||
const ozz::math::Float3 box_center_ = (_box.max + _box.min) * .5f;
|
||||
distance_ = Length(box_center_ - camera_pos);
|
||||
center_ = camera_pos + camera_dir * distance_;
|
||||
angles_.x = asinf(camera_dir.y);
|
||||
angles_.y = atan2(-camera_dir.x, -camera_dir.z);
|
||||
}
|
||||
}
|
||||
|
||||
// Update manual controls.
|
||||
const Controls controls = UpdateControls(_delta_time);
|
||||
|
||||
// Disable autoframing according to inputs.
|
||||
auto_framing_ &= !controls.panning && !controls.rotating &&
|
||||
!controls.zooming && !controls.zooming_wheel;
|
||||
|
||||
if (auto_framing_) {
|
||||
view_ = Invert(_transform);
|
||||
}
|
||||
}
|
||||
|
||||
Camera::Controls Camera::UpdateControls(float _delta_time) {
|
||||
Controls controls;
|
||||
controls.zooming = false;
|
||||
controls.zooming_wheel = false;
|
||||
controls.rotating = false;
|
||||
controls.panning = false;
|
||||
|
||||
// Mouse wheel + SHIFT activates Zoom.
|
||||
if (glfwGetKey(GLFW_KEY_LSHIFT) == GLFW_PRESS) {
|
||||
const int w = glfwGetMouseWheel();
|
||||
const int dw = w - mouse_last_wheel_;
|
||||
mouse_last_wheel_ = w;
|
||||
if (dw != 0) {
|
||||
controls.zooming_wheel = true;
|
||||
distance_ *= 1.f + -dw * kScrollFactor;
|
||||
}
|
||||
} else {
|
||||
mouse_last_wheel_ = glfwGetMouseWheel();
|
||||
}
|
||||
|
||||
// Fetches current mouse position and compute its movement since last frame.
|
||||
int x, y;
|
||||
glfwGetMousePos(&x, &y);
|
||||
const int mdx = x - mouse_last_x_;
|
||||
const int mdy = y - mouse_last_y_;
|
||||
mouse_last_x_ = x;
|
||||
mouse_last_y_ = y;
|
||||
|
||||
// Finds keyboard relative dx and dy commmands.
|
||||
const int timed_factor =
|
||||
ozz::math::Max(1, static_cast<int>(kKeyboardFactor * _delta_time));
|
||||
const int kdx =
|
||||
timed_factor * (glfwGetKey(GLFW_KEY_LEFT) - glfwGetKey(GLFW_KEY_RIGHT));
|
||||
const int kdy =
|
||||
timed_factor * (glfwGetKey(GLFW_KEY_DOWN) - glfwGetKey(GLFW_KEY_UP));
|
||||
const bool keyboard_interact = kdx || kdy;
|
||||
|
||||
// Computes composed keyboard and mouse dx and dy.
|
||||
const int dx = mdx + kdx;
|
||||
const int dy = mdy + kdy;
|
||||
|
||||
// Mouse right button activates Zoom, Pan and Orbit modes.
|
||||
if (keyboard_interact ||
|
||||
glfwGetMouseButton(GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS) {
|
||||
if (glfwGetKey(GLFW_KEY_LSHIFT) == GLFW_PRESS) { // Zoom mode.
|
||||
controls.zooming = true;
|
||||
|
||||
distance_ += dy * kDistanceFactor;
|
||||
} else if (glfwGetKey(GLFW_KEY_LALT) == GLFW_PRESS) { // Pan mode.
|
||||
controls.panning = true;
|
||||
|
||||
const float dx_pan = -dx * kPanFactor;
|
||||
const float dy_pan = -dy * kPanFactor;
|
||||
|
||||
// Moves along camera axes.
|
||||
math::Float4x4 transpose = Transpose(view_);
|
||||
math::Float3 right_transpose, up_transpose;
|
||||
math::Store3PtrU(transpose.cols[0], &right_transpose.x);
|
||||
math::Store3PtrU(transpose.cols[1], &up_transpose.x);
|
||||
center_ = center_ + right_transpose * dx_pan + up_transpose * dy_pan;
|
||||
} else { // Orbit mode.
|
||||
controls.rotating = true;
|
||||
|
||||
angles_.x = fmodf(angles_.x - dy * kAngleFactor, ozz::math::k2Pi);
|
||||
angles_.y = fmodf(angles_.y - dx * kAngleFactor, ozz::math::k2Pi);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the model view matrix components.
|
||||
const Float4x4 center = Float4x4::Translation(
|
||||
math::simd_float4::Load(center_.x, center_.y, center_.z, 1.f));
|
||||
const Float4x4 y_rotation = Float4x4::FromAxisAngle(
|
||||
math::simd_float4::y_axis(), math::simd_float4::Load1(angles_.y));
|
||||
const Float4x4 x_rotation = Float4x4::FromAxisAngle(
|
||||
math::simd_float4::x_axis(), math::simd_float4::Load1(angles_.x));
|
||||
const Float4x4 distance =
|
||||
Float4x4::Translation(math::simd_float4::Load(0.f, 0.f, distance_, 1.f));
|
||||
|
||||
// Concatenate view matrix components.
|
||||
view_ = Invert(center * y_rotation * x_rotation * distance);
|
||||
|
||||
return controls;
|
||||
}
|
||||
|
||||
void Camera::Reset(const math::Float3& _center, const math::Float2& _angles,
|
||||
float _distance) {
|
||||
center_ = _center;
|
||||
angles_ = _angles;
|
||||
distance_ = _distance;
|
||||
}
|
||||
|
||||
void Camera::OnGui(ImGui* _im_gui) {
|
||||
const char* controls_label =
|
||||
"-RMB: Rotate\n"
|
||||
"-Shift + Wheel: Zoom\n"
|
||||
"-Shift + RMB: Zoom\n"
|
||||
"-Alt + RMB: Pan\n";
|
||||
_im_gui->DoLabel(controls_label, ImGui::kLeft, false);
|
||||
|
||||
_im_gui->DoCheckBox("Automatic", &auto_framing_);
|
||||
}
|
||||
|
||||
void Camera::Bind3D() {
|
||||
// Updates internal vp matrix.
|
||||
view_proj_ = projection_ * view_;
|
||||
}
|
||||
|
||||
void Camera::Bind2D() {
|
||||
// Updates internal vp matrix. View matrix is identity.
|
||||
view_proj_ = projection_2d_;
|
||||
}
|
||||
|
||||
void Camera::Resize(int _width, int _height) {
|
||||
// Handle empty windows.
|
||||
if (_width <= 0 || _height <= 0) {
|
||||
projection_ = ozz::math::Float4x4::identity();
|
||||
projection_2d_ = ozz::math::Float4x4::identity();
|
||||
return;
|
||||
}
|
||||
|
||||
// Compute the 3D projection matrix.
|
||||
const float ratio = 1.f * _width / _height;
|
||||
const float h = tan(kFovY * .5f) * kNear;
|
||||
const float w = h * ratio;
|
||||
|
||||
projection_.cols[0] = math::simd_float4::Load(kNear / w, 0.f, 0.f, 0.f);
|
||||
projection_.cols[1] = math::simd_float4::Load(0.f, kNear / h, 0.f, 0.f);
|
||||
projection_.cols[2] =
|
||||
math::simd_float4::Load(0.f, 0.f, -(kFar + kNear) / (kFar - kNear), -1.f);
|
||||
projection_.cols[3] = math::simd_float4::Load(
|
||||
0.f, 0.f, -(2.f * kFar * kNear) / (kFar - kNear), 0.f);
|
||||
|
||||
// Computes the 2D projection matrix.
|
||||
projection_2d_.cols[0] = math::simd_float4::Load(2.f / _width, 0.f, 0.f, 0.f);
|
||||
projection_2d_.cols[1] =
|
||||
math::simd_float4::Load(0.f, 2.f / _height, 0.f, 0.f);
|
||||
projection_2d_.cols[2] = math::simd_float4::Load(0.f, 0.f, -2.0f, 0.f);
|
||||
projection_2d_.cols[3] = math::simd_float4::Load(-1.f, -1.f, 0.f, 1.f);
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
@@ -0,0 +1,136 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_CAMERA_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_CAMERA_H_
|
||||
|
||||
#ifndef OZZ_INCLUDE_PRIVATE_HEADER
|
||||
#error "This header is private, it cannot be included from public headers."
|
||||
#endif // OZZ_INCLUDE_PRIVATE_HEADER
|
||||
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
#include "ozz/base/maths/vec_float.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
struct Box;
|
||||
}
|
||||
namespace sample {
|
||||
class ImGui;
|
||||
namespace internal {
|
||||
|
||||
// Framework internal implementation of an OpenGL/glfw camera system that can be
|
||||
// manipulated with the mouse and some shortcuts.
|
||||
class Camera {
|
||||
public:
|
||||
// Initializes camera to its default framing.
|
||||
Camera();
|
||||
|
||||
// Destructor.
|
||||
~Camera();
|
||||
|
||||
// Updates camera framing: mouse manipulation, timed transitions...
|
||||
// Returns actions that the user applied to the camera during the frame.
|
||||
void Update(const math::Box& _box, float _delta_time, bool _first_frame);
|
||||
|
||||
// Updates camera location, overriding user inputs.
|
||||
// Returns actions that the user applied to the camera during the frame.
|
||||
void Update(const math::Float4x4& _transform, const math::Box& _box,
|
||||
float _delta_time, bool _first_frame);
|
||||
|
||||
// Resets camera center, angles and distance.
|
||||
void Reset(const math::Float3& _center, const math::Float2& _angles,
|
||||
float _distance);
|
||||
|
||||
// Provides immediate mode gui display event.
|
||||
void OnGui(ImGui* _im_gui);
|
||||
|
||||
// Binds 3d projection and view matrices to the current matrix.
|
||||
void Bind3D();
|
||||
|
||||
// Binds 2d projection and view matrices to the current matrix.
|
||||
void Bind2D();
|
||||
|
||||
// Resize notification, used to rebuild projection matrix.
|
||||
void Resize(int _width, int _height);
|
||||
|
||||
// Get the current projection matrix.
|
||||
const math::Float4x4& projection() { return projection_; }
|
||||
|
||||
// Get the current model-view matrix.
|
||||
const math::Float4x4& view() { return view_; }
|
||||
|
||||
// Get the current model-view-projection matrix.
|
||||
const math::Float4x4& view_proj() { return view_proj_; }
|
||||
|
||||
// Set to true to automatically frame the camera on the whole scene.
|
||||
void set_auto_framing(bool _auto) { auto_framing_ = _auto; }
|
||||
// Get auto framing state.
|
||||
bool auto_framing() const { return auto_framing_; }
|
||||
|
||||
private:
|
||||
struct Controls {
|
||||
bool zooming;
|
||||
bool zooming_wheel;
|
||||
bool rotating;
|
||||
bool panning;
|
||||
};
|
||||
Controls UpdateControls(float _delta_time);
|
||||
|
||||
// The current projection matrix.
|
||||
math::Float4x4 projection_;
|
||||
|
||||
// The current projection matrix.
|
||||
math::Float4x4 projection_2d_;
|
||||
|
||||
// The current model-view matrix.
|
||||
math::Float4x4 view_;
|
||||
|
||||
// The current model-view-projection matrix.
|
||||
math::Float4x4 view_proj_;
|
||||
|
||||
// The angles in degree of the camera rotation around x and y axes.
|
||||
math::Float2 angles_;
|
||||
|
||||
// The center of the rotation.
|
||||
math::Float3 center_;
|
||||
|
||||
// The view distance, from the center of rotation.
|
||||
float distance_;
|
||||
|
||||
// The position of the mouse, the last time it has been seen.
|
||||
int mouse_last_x_;
|
||||
int mouse_last_y_;
|
||||
int mouse_last_wheel_;
|
||||
|
||||
// Set to true to automatically frame the camera on the whole scene.
|
||||
bool auto_framing_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_CAMERA_H_
|
||||
@@ -0,0 +1,171 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_ICOSPHERE_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_ICOSPHERE_H_
|
||||
|
||||
#include "ozz/base/platform.h"
|
||||
|
||||
// Precomputed normalized icosphere with 2 levels of subdivisions.
|
||||
// Note that kVertices can also be used as normals.
|
||||
namespace icosphere {
|
||||
|
||||
static const float kVertices[] = {
|
||||
-0.682f, 0.717f, 0.148f, -0.588f, 0.688f, 0.425f, -0.443f, 0.864f,
|
||||
0.239f, -0.526f, 0.851f, 0.000f, -0.809f, 0.500f, 0.309f, -0.309f,
|
||||
0.809f, 0.500f, -0.717f, 0.148f, 0.682f, -0.688f, 0.425f, 0.588f,
|
||||
-0.864f, 0.239f, 0.443f, -0.851f, 0.000f, 0.526f, -0.500f, 0.309f,
|
||||
0.809f, -0.148f, 0.682f, 0.717f, -0.425f, 0.588f, 0.688f, -0.239f,
|
||||
0.443f, 0.864f, 0.000f, 0.526f, 0.851f, -0.162f, 0.951f, 0.263f,
|
||||
-0.295f, 0.955f, 0.000f, 0.000f, 1.000f, 0.000f, 0.148f, 0.682f,
|
||||
0.717f, 0.000f, 0.851f, 0.526f, 0.309f, 0.809f, 0.500f, 0.295f,
|
||||
0.955f, 0.000f, 0.162f, 0.951f, 0.263f, 0.443f, 0.864f, 0.239f,
|
||||
0.526f, 0.851f, 0.000f, -0.162f, 0.951f, -0.263f, -0.443f, 0.864f,
|
||||
-0.239f, -0.309f, 0.809f, -0.500f, 0.443f, 0.864f, -0.239f, 0.162f,
|
||||
0.951f, -0.263f, 0.309f, 0.809f, -0.500f, -0.148f, 0.682f, -0.717f,
|
||||
0.000f, 0.851f, -0.526f, 0.148f, 0.682f, -0.717f, 0.000f, 0.526f,
|
||||
-0.851f, -0.588f, 0.688f, -0.425f, -0.682f, 0.717f, -0.148f, -0.809f,
|
||||
0.500f, -0.309f, -0.239f, 0.443f, -0.864f, -0.425f, 0.588f, -0.688f,
|
||||
-0.500f, 0.309f, -0.809f, -0.864f, 0.239f, -0.443f, -0.688f, 0.425f,
|
||||
-0.588f, -0.717f, 0.148f, -0.682f, -0.851f, 0.000f, -0.526f, -0.851f,
|
||||
0.526f, 0.000f, -0.955f, 0.000f, -0.295f, -0.951f, 0.263f, -0.162f,
|
||||
-1.000f, 0.000f, 0.000f, -0.951f, 0.263f, 0.162f, -0.955f, 0.000f,
|
||||
0.295f, 0.588f, 0.688f, 0.425f, 0.682f, 0.717f, 0.148f, 0.809f,
|
||||
0.500f, 0.309f, 0.239f, 0.443f, 0.864f, 0.425f, 0.588f, 0.688f,
|
||||
0.500f, 0.309f, 0.809f, 0.864f, 0.239f, 0.443f, 0.688f, 0.425f,
|
||||
0.588f, 0.717f, 0.148f, 0.682f, 0.851f, 0.000f, 0.526f, -0.263f,
|
||||
0.162f, 0.951f, 0.000f, 0.295f, 0.955f, 0.000f, 0.000f, 1.000f,
|
||||
-0.717f, -0.148f, 0.682f, -0.526f, 0.000f, 0.851f, -0.500f, -0.309f,
|
||||
0.809f, 0.000f, -0.295f, 0.955f, -0.263f, -0.162f, 0.951f, -0.239f,
|
||||
-0.443f, 0.864f, 0.000f, -0.526f, 0.851f, -0.951f, -0.263f, 0.162f,
|
||||
-0.864f, -0.239f, 0.443f, -0.809f, -0.500f, 0.309f, -0.864f, -0.239f,
|
||||
-0.443f, -0.951f, -0.263f, -0.162f, -0.809f, -0.500f, -0.309f, -0.682f,
|
||||
-0.717f, 0.148f, -0.851f, -0.526f, 0.000f, -0.682f, -0.717f, -0.148f,
|
||||
-0.526f, -0.851f, 0.000f, -0.526f, 0.000f, -0.851f, -0.717f, -0.148f,
|
||||
-0.682f, -0.500f, -0.309f, -0.809f, 0.000f, 0.295f, -0.955f, -0.263f,
|
||||
0.162f, -0.951f, 0.000f, 0.000f, -1.000f, -0.239f, -0.443f, -0.864f,
|
||||
-0.263f, -0.162f, -0.951f, 0.000f, -0.295f, -0.955f, 0.000f, -0.526f,
|
||||
-0.851f, 0.425f, 0.588f, -0.688f, 0.239f, 0.443f, -0.864f, 0.500f,
|
||||
0.309f, -0.809f, 0.682f, 0.717f, -0.148f, 0.588f, 0.688f, -0.425f,
|
||||
0.809f, 0.500f, -0.309f, 0.717f, 0.148f, -0.682f, 0.688f, 0.425f,
|
||||
-0.588f, 0.864f, 0.239f, -0.443f, 0.851f, 0.000f, -0.526f, 0.682f,
|
||||
-0.717f, 0.148f, 0.588f, -0.688f, 0.425f, 0.443f, -0.864f, 0.239f,
|
||||
0.526f, -0.851f, 0.000f, 0.809f, -0.500f, 0.309f, 0.309f, -0.809f,
|
||||
0.500f, 0.717f, -0.148f, 0.682f, 0.688f, -0.425f, 0.588f, 0.864f,
|
||||
-0.239f, 0.443f, 0.500f, -0.309f, 0.809f, 0.148f, -0.682f, 0.717f,
|
||||
0.425f, -0.588f, 0.688f, 0.239f, -0.443f, 0.864f, 0.162f, -0.951f,
|
||||
0.263f, 0.295f, -0.955f, 0.000f, 0.000f, -1.000f, 0.000f, -0.148f,
|
||||
-0.682f, 0.717f, 0.000f, -0.851f, 0.526f, -0.309f, -0.809f, 0.500f,
|
||||
-0.295f, -0.955f, 0.000f, -0.162f, -0.951f, 0.263f, -0.443f, -0.864f,
|
||||
0.239f, 0.162f, -0.951f, -0.263f, 0.443f, -0.864f, -0.239f, 0.309f,
|
||||
-0.809f, -0.500f, -0.443f, -0.864f, -0.239f, -0.162f, -0.951f, -0.263f,
|
||||
-0.309f, -0.809f, -0.500f, 0.148f, -0.682f, -0.717f, 0.000f, -0.851f,
|
||||
-0.526f, -0.148f, -0.682f, -0.717f, 0.588f, -0.688f, -0.425f, 0.682f,
|
||||
-0.717f, -0.148f, 0.809f, -0.500f, -0.309f, 0.239f, -0.443f, -0.864f,
|
||||
0.425f, -0.588f, -0.688f, 0.500f, -0.309f, -0.809f, 0.864f, -0.239f,
|
||||
-0.443f, 0.688f, -0.425f, -0.588f, 0.717f, -0.148f, -0.682f, 0.851f,
|
||||
-0.526f, 0.000f, 0.955f, 0.000f, -0.295f, 0.951f, -0.263f, -0.162f,
|
||||
1.000f, 0.000f, 0.000f, 0.951f, -0.263f, 0.162f, 0.955f, 0.000f,
|
||||
0.295f, 0.263f, -0.162f, 0.951f, 0.526f, 0.000f, 0.851f, 0.263f,
|
||||
0.162f, 0.951f, -0.588f, -0.688f, 0.425f, -0.425f, -0.588f, 0.688f,
|
||||
-0.688f, -0.425f, 0.588f, -0.425f, -0.588f, -0.688f, -0.588f, -0.688f,
|
||||
-0.425f, -0.688f, -0.425f, -0.588f, 0.526f, 0.000f, -0.851f, 0.263f,
|
||||
-0.162f, -0.951f, 0.263f, 0.162f, -0.951f, 0.951f, 0.263f, 0.162f,
|
||||
0.951f, 0.263f, -0.162f, 0.851f, 0.526f, 0.000f};
|
||||
|
||||
static const int kNumVertices = OZZ_ARRAY_SIZE(kVertices);
|
||||
|
||||
static const uint16_t kIndices[] = {
|
||||
3, 0, 2, 4, 1, 0, 5, 2, 1, 0, 1, 2, 9, 6, 8,
|
||||
10, 7, 6, 4, 8, 7, 6, 7, 8, 14, 11, 13, 5, 12, 11,
|
||||
10, 13, 12, 11, 12, 13, 4, 7, 1, 10, 12, 7, 5, 1, 12,
|
||||
7, 12, 1, 3, 2, 16, 5, 15, 2, 17, 16, 15, 2, 15, 16,
|
||||
14, 18, 11, 20, 19, 18, 5, 11, 19, 18, 19, 11, 24, 21, 23,
|
||||
17, 22, 21, 20, 23, 22, 21, 22, 23, 5, 19, 15, 20, 22, 19,
|
||||
17, 15, 22, 19, 22, 15, 3, 16, 26, 17, 25, 16, 27, 26, 25,
|
||||
16, 25, 26, 24, 28, 21, 30, 29, 28, 17, 21, 29, 28, 29, 21,
|
||||
34, 31, 33, 27, 32, 31, 30, 33, 32, 31, 32, 33, 17, 29, 25,
|
||||
30, 32, 29, 27, 25, 32, 29, 32, 25, 3, 26, 36, 27, 35, 26,
|
||||
37, 36, 35, 26, 35, 36, 34, 38, 31, 40, 39, 38, 27, 31, 39,
|
||||
38, 39, 31, 44, 41, 43, 37, 42, 41, 40, 43, 42, 41, 42, 43,
|
||||
27, 39, 35, 40, 42, 39, 37, 35, 42, 39, 42, 35, 3, 36, 0,
|
||||
37, 45, 36, 4, 0, 45, 36, 45, 0, 44, 46, 41, 48, 47, 46,
|
||||
37, 41, 47, 46, 47, 41, 9, 8, 50, 4, 49, 8, 48, 50, 49,
|
||||
8, 49, 50, 37, 47, 45, 48, 49, 47, 4, 45, 49, 47, 49, 45,
|
||||
24, 23, 52, 20, 51, 23, 53, 52, 51, 23, 51, 52, 14, 54, 18,
|
||||
56, 55, 54, 20, 18, 55, 54, 55, 18, 60, 57, 59, 53, 58, 57,
|
||||
56, 59, 58, 57, 58, 59, 20, 55, 51, 56, 58, 55, 53, 51, 58,
|
||||
55, 58, 51, 14, 13, 62, 10, 61, 13, 63, 62, 61, 13, 61, 62,
|
||||
9, 64, 6, 66, 65, 64, 10, 6, 65, 64, 65, 6, 70, 67, 69,
|
||||
63, 68, 67, 66, 69, 68, 67, 68, 69, 10, 65, 61, 66, 68, 65,
|
||||
63, 61, 68, 65, 68, 61, 9, 50, 72, 48, 71, 50, 73, 72, 71,
|
||||
50, 71, 72, 44, 74, 46, 76, 75, 74, 48, 46, 75, 74, 75, 46,
|
||||
80, 77, 79, 73, 78, 77, 76, 79, 78, 77, 78, 79, 48, 75, 71,
|
||||
76, 78, 75, 73, 71, 78, 75, 78, 71, 44, 43, 82, 40, 81, 43,
|
||||
83, 82, 81, 43, 81, 82, 34, 84, 38, 86, 85, 84, 40, 38, 85,
|
||||
84, 85, 38, 90, 87, 89, 83, 88, 87, 86, 89, 88, 87, 88, 89,
|
||||
40, 85, 81, 86, 88, 85, 83, 81, 88, 85, 88, 81, 34, 33, 92,
|
||||
30, 91, 33, 93, 92, 91, 33, 91, 92, 24, 94, 28, 96, 95, 94,
|
||||
30, 28, 95, 94, 95, 28, 100, 97, 99, 93, 98, 97, 96, 99, 98,
|
||||
97, 98, 99, 30, 95, 91, 96, 98, 95, 93, 91, 98, 95, 98, 91,
|
||||
104, 101, 103, 105, 102, 101, 106, 103, 102, 101, 102, 103, 60, 107, 109,
|
||||
110, 108, 107, 105, 109, 108, 107, 108, 109, 70, 111, 113, 106, 112, 111,
|
||||
110, 113, 112, 111, 112, 113, 105, 108, 102, 110, 112, 108, 106, 102, 112,
|
||||
108, 112, 102, 104, 103, 115, 106, 114, 103, 116, 115, 114, 103, 114, 115,
|
||||
70, 117, 111, 119, 118, 117, 106, 111, 118, 117, 118, 111, 80, 120, 122,
|
||||
116, 121, 120, 119, 122, 121, 120, 121, 122, 106, 118, 114, 119, 121, 118,
|
||||
116, 114, 121, 118, 121, 114, 104, 115, 124, 116, 123, 115, 125, 124, 123,
|
||||
115, 123, 124, 80, 126, 120, 128, 127, 126, 116, 120, 127, 126, 127, 120,
|
||||
90, 129, 131, 125, 130, 129, 128, 131, 130, 129, 130, 131, 116, 127, 123,
|
||||
128, 130, 127, 125, 123, 130, 127, 130, 123, 104, 124, 133, 125, 132, 124,
|
||||
134, 133, 132, 124, 132, 133, 90, 135, 129, 137, 136, 135, 125, 129, 136,
|
||||
135, 136, 129, 100, 138, 140, 134, 139, 138, 137, 140, 139, 138, 139, 140,
|
||||
125, 136, 132, 137, 139, 136, 134, 132, 139, 136, 139, 132, 104, 133, 101,
|
||||
134, 141, 133, 105, 101, 141, 133, 141, 101, 100, 142, 138, 144, 143, 142,
|
||||
134, 138, 143, 142, 143, 138, 60, 109, 146, 105, 145, 109, 144, 146, 145,
|
||||
109, 145, 146, 134, 143, 141, 144, 145, 143, 105, 141, 145, 143, 145, 141,
|
||||
70, 113, 67, 110, 147, 113, 63, 67, 147, 113, 147, 67, 60, 59, 107,
|
||||
56, 148, 59, 110, 107, 148, 59, 148, 107, 14, 62, 54, 63, 149, 62,
|
||||
56, 54, 149, 62, 149, 54, 110, 148, 147, 56, 149, 148, 63, 147, 149,
|
||||
148, 149, 147, 80, 122, 77, 119, 150, 122, 73, 77, 150, 122, 150, 77,
|
||||
70, 69, 117, 66, 151, 69, 119, 117, 151, 69, 151, 117, 9, 72, 64,
|
||||
73, 152, 72, 66, 64, 152, 72, 152, 64, 119, 151, 150, 66, 152, 151,
|
||||
73, 150, 152, 151, 152, 150, 90, 131, 87, 128, 153, 131, 83, 87, 153,
|
||||
131, 153, 87, 80, 79, 126, 76, 154, 79, 128, 126, 154, 79, 154, 126,
|
||||
44, 82, 74, 83, 155, 82, 76, 74, 155, 82, 155, 74, 128, 154, 153,
|
||||
76, 155, 154, 83, 153, 155, 154, 155, 153, 100, 140, 97, 137, 156, 140,
|
||||
93, 97, 156, 140, 156, 97, 90, 89, 135, 86, 157, 89, 137, 135, 157,
|
||||
89, 157, 135, 34, 92, 84, 93, 158, 92, 86, 84, 158, 92, 158, 84,
|
||||
137, 157, 156, 86, 158, 157, 93, 156, 158, 157, 158, 156, 60, 146, 57,
|
||||
144, 159, 146, 53, 57, 159, 146, 159, 57, 100, 99, 142, 96, 160, 99,
|
||||
144, 142, 160, 99, 160, 142, 24, 52, 94, 53, 161, 52, 96, 94, 161,
|
||||
52, 161, 94, 144, 160, 159, 96, 161, 160, 53, 159, 161, 160, 161, 159};
|
||||
|
||||
static const int kNumIndices = OZZ_ARRAY_SIZE(kIndices);
|
||||
|
||||
} // namespace icosphere
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_ICOSPHERE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,233 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMGUI_IMPL_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMGUI_IMPL_H_
|
||||
|
||||
#ifndef OZZ_INCLUDE_PRIVATE_HEADER
|
||||
#error "This header is private, it cannot be included from public headers."
|
||||
#endif // OZZ_INCLUDE_PRIVATE_HEADER
|
||||
|
||||
// Implements immediate mode gui.
|
||||
// See imgui.h for details about function specifications.
|
||||
|
||||
#include "framework/imgui.h"
|
||||
|
||||
#include "ozz/base/containers/vector.h"
|
||||
#include "ozz/base/maths/rect.h"
|
||||
|
||||
#include "renderer_impl.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
class RendererImpl;
|
||||
|
||||
// Immediate mode gui implementation.
|
||||
class ImGuiImpl : public ImGui {
|
||||
public:
|
||||
ImGuiImpl();
|
||||
virtual ~ImGuiImpl();
|
||||
|
||||
// Input state.
|
||||
struct Inputs {
|
||||
// Default input values.
|
||||
Inputs() : mouse_x(0), mouse_y(0), lmb_pressed(false) {}
|
||||
|
||||
// Cursor x position. 0 indicates the screen left border.
|
||||
int mouse_x;
|
||||
// Cursor y position. 0 indicates the screen bottom border.
|
||||
int mouse_y;
|
||||
// Left mouse button state. true when the left mouse button is pressed.
|
||||
bool lmb_pressed;
|
||||
};
|
||||
|
||||
// Starts an imgui frame.
|
||||
// _inputs describes next frame inputs. It is internally copied.
|
||||
// _rect is the windows size.
|
||||
void BeginFrame(const Inputs& _inputs, const math::RectInt& _rect,
|
||||
RendererImpl* _renderer);
|
||||
|
||||
// Ends the current imgui frame.
|
||||
void EndFrame();
|
||||
|
||||
protected:
|
||||
// Starts ImGui interface implementation.
|
||||
// See imgui.h for virtual function specifications.
|
||||
|
||||
virtual void BeginContainer(const char* _title, const math::RectFloat* _rect,
|
||||
bool* _open, bool _constrain);
|
||||
|
||||
virtual void EndContainer();
|
||||
|
||||
virtual bool DoButton(const char* _label, bool _enabled, bool* _state);
|
||||
|
||||
virtual bool DoSlider(const char* _label, float _min, float _max,
|
||||
float* _value, float _pow, bool _enabled);
|
||||
|
||||
virtual bool DoSlider(const char* _label, int _min, int _max, int* _value,
|
||||
float _pow, bool _enabled);
|
||||
|
||||
virtual bool DoCheckBox(const char* _label, bool* _state, bool _enabled);
|
||||
|
||||
virtual bool DoRadioButton(int _ref, const char* _label, int* _value,
|
||||
bool _enabled);
|
||||
|
||||
virtual void DoLabel(const char* _label, Justification _justification,
|
||||
bool _single_line);
|
||||
|
||||
virtual void DoGraph(const char* _label, float _min, float _max, float _mean,
|
||||
const float* _value_cursor, const float* _value_begin,
|
||||
const float* _value_end);
|
||||
|
||||
private:
|
||||
// Computes the rect of a new widget to add.
|
||||
// Returns true if there is enough space for a new widget.
|
||||
bool AddWidget(float _height, math::RectFloat* _rect);
|
||||
|
||||
// Implements button logic.
|
||||
// Returns true if the button was clicked.
|
||||
bool ButtonLogic(const math::RectFloat& _rect, int _id, bool* _hot,
|
||||
bool* _active);
|
||||
|
||||
// Fills a rectangle with _rect coordinates. Draws rounded angles if _radius
|
||||
// is greater than 0.
|
||||
// If _texture id is not 0, then texture with id _texture is mapped using a
|
||||
// planar projection to the rect.
|
||||
void FillRect(const math::RectFloat& _rect, float _radius,
|
||||
const GLubyte _rgba[4]) const;
|
||||
void FillRect(const math::RectFloat& _rect, float _radius,
|
||||
const GLubyte _rgba[4],
|
||||
const ozz::math::Float4x4& _transform) const;
|
||||
|
||||
// Strokes a rectangle with _rect coordinates. Draws rounded angles if _radius
|
||||
// is greater than 0.
|
||||
void StrokeRect(const math::RectFloat& _rect, float _radius,
|
||||
const GLubyte _rgba[4]) const;
|
||||
void StrokeRect(const math::RectFloat& _rect, float _radius,
|
||||
const GLubyte _rgba[4],
|
||||
const ozz::math::Float4x4& _transform) const;
|
||||
|
||||
enum PrintLayout {
|
||||
kNorthWest,
|
||||
kNorth,
|
||||
kNorthEst,
|
||||
kWest,
|
||||
kMiddle,
|
||||
kEst,
|
||||
kSouthWest,
|
||||
kSouth,
|
||||
kSouthEst,
|
||||
};
|
||||
|
||||
// Print _text in _rect.
|
||||
float Print(const char* _text, const math::RectFloat& _rect,
|
||||
PrintLayout _layout, const GLubyte _rgba[4]) const;
|
||||
|
||||
// Initialize circle vertices.
|
||||
void InitializeCircle();
|
||||
|
||||
// Initializes and destroys the internal font rendering system.
|
||||
void InitalizeFont();
|
||||
void DestroyFont();
|
||||
|
||||
// ImGui state.
|
||||
|
||||
// Current frame inputs.
|
||||
Inputs inputs_;
|
||||
|
||||
// Internal states.
|
||||
// The hot item is the one that's below the mouse cursor.
|
||||
int hot_item_;
|
||||
|
||||
// The active item is the one being currently interacted with.
|
||||
int active_item_;
|
||||
|
||||
// The automatically generated widget identifier.
|
||||
int auto_gen_id_;
|
||||
|
||||
struct Container {
|
||||
// The current rect.
|
||||
math::RectFloat rect;
|
||||
|
||||
// The y offset of the top of the next widget in the current container.
|
||||
float offset_y;
|
||||
|
||||
// Constrains container height to the size used by controls in the
|
||||
// container.
|
||||
bool constrain;
|
||||
};
|
||||
|
||||
// Container stack.
|
||||
ozz::vector<Container> containers_;
|
||||
|
||||
// Round rendering.
|
||||
|
||||
// Defines the number of segments used by the precomputed circle.
|
||||
// Must be multiple of 4.
|
||||
static const int kCircleSegments = 8;
|
||||
|
||||
// Circle vertices coordinates (cosine/sinus)
|
||||
float circle_[kCircleSegments][2];
|
||||
|
||||
// Font rendering.
|
||||
|
||||
// Declares font's structure.
|
||||
struct Font {
|
||||
int texture_width; // width of the pow2 texture.
|
||||
int texture_height; // height of the pow2 texture.
|
||||
int image_width; // width of the image area in the texture.
|
||||
int image_height; // height of the image area in the texture.
|
||||
int glyph_height;
|
||||
int glyph_width;
|
||||
int glyph_count;
|
||||
unsigned char glyph_start; // ascii code of the first character.
|
||||
const unsigned char* pixels;
|
||||
size_t pixels_size;
|
||||
};
|
||||
|
||||
// Declares the font instance.
|
||||
static const Font font_;
|
||||
|
||||
// Pre-cooked glyphes uv and vertex coordinates.
|
||||
struct Glyph {
|
||||
float uv[4][2];
|
||||
float pos[4][2];
|
||||
};
|
||||
Glyph glyphes_[256];
|
||||
|
||||
// Glyph GL texture
|
||||
unsigned int glyph_texture_;
|
||||
|
||||
// Renderer, available between Begin/EndFrame
|
||||
RendererImpl* renderer_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMGUI_IMPL_H_
|
||||
@@ -0,0 +1,116 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define OZZ_INCLUDE_PRIVATE_HEADER // Allows to include private headers.
|
||||
|
||||
#include "immediate.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "camera.h"
|
||||
#include "ozz/base/memory/allocator.h"
|
||||
#include "renderer_impl.h"
|
||||
#include "shader.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
GlImmediateRenderer::GlImmediateRenderer(RendererImpl* _renderer)
|
||||
: vbo_(0), size_(0), renderer_(_renderer) {}
|
||||
|
||||
GlImmediateRenderer::~GlImmediateRenderer() {
|
||||
assert(size_ == 0 && "Immediate rendering still in use.");
|
||||
|
||||
if (vbo_) {
|
||||
GL(DeleteBuffers(1, &vbo_));
|
||||
vbo_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool GlImmediateRenderer::Initialize() {
|
||||
GL(GenBuffers(1, &vbo_));
|
||||
|
||||
immediate_pc_shader = ImmediatePCShader::Build();
|
||||
if (!immediate_pc_shader) {
|
||||
return false;
|
||||
}
|
||||
immediate_ptc_shader = ImmediatePTCShader::Build();
|
||||
if (!immediate_ptc_shader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlImmediateRenderer::Begin() {
|
||||
assert(size_ == 0 && "Immediate rendering already in use.");
|
||||
}
|
||||
|
||||
template <>
|
||||
void GlImmediateRenderer::End<VertexPC>(GLenum _mode,
|
||||
const ozz::math::Float4x4& _transform) {
|
||||
GL(BindBuffer(GL_ARRAY_BUFFER, vbo_));
|
||||
GL(BufferData(GL_ARRAY_BUFFER, size_, buffer_.data(), GL_STREAM_DRAW));
|
||||
|
||||
immediate_pc_shader->Bind(_transform, renderer_->camera()->view_proj(),
|
||||
sizeof(VertexPC), 0, sizeof(VertexPC), 12);
|
||||
|
||||
const int count = static_cast<int>(size_ / sizeof(VertexPC));
|
||||
GL(DrawArrays(_mode, 0, count));
|
||||
|
||||
immediate_pc_shader->Unbind();
|
||||
|
||||
GL(BindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// Reset vertex count for the next call
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
void GlImmediateRenderer::End<VertexPTC>(
|
||||
GLenum _mode, const ozz::math::Float4x4& _transform) {
|
||||
GL(BindBuffer(GL_ARRAY_BUFFER, vbo_));
|
||||
GL(BufferData(GL_ARRAY_BUFFER, size_, buffer_.data(), GL_STREAM_DRAW));
|
||||
|
||||
immediate_ptc_shader->Bind(_transform, renderer_->camera()->view_proj(),
|
||||
sizeof(VertexPTC), 0, sizeof(VertexPTC), 12,
|
||||
sizeof(VertexPTC), 20);
|
||||
|
||||
const int count = static_cast<int>(size_ / sizeof(VertexPTC));
|
||||
GL(DrawArrays(_mode, 0, count));
|
||||
|
||||
immediate_ptc_shader->Unbind();
|
||||
|
||||
GL(BindBuffer(GL_ARRAY_BUFFER, 0));
|
||||
|
||||
// Reset vertex count for the next call
|
||||
size_ = 0;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
@@ -0,0 +1,173 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMMEDIATE_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMMEDIATE_H_
|
||||
|
||||
#ifndef OZZ_INCLUDE_PRIVATE_HEADER
|
||||
#error "This header is private, it cannot be included from public headers."
|
||||
#endif // OZZ_INCLUDE_PRIVATE_HEADER
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "ozz/base/containers/vector.h"
|
||||
#include "ozz/base/maths/math_ex.h"
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
#include "ozz/base/memory/unique_ptr.h"
|
||||
#include "ozz/base/platform.h"
|
||||
#include "renderer_impl.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
class RendererImpl;
|
||||
class ImmediatePCShader;
|
||||
class ImmediatePNShader;
|
||||
class ImmediatePTCShader;
|
||||
|
||||
// Declares supported vertex formats.
|
||||
// Position + Color.
|
||||
struct VertexPC {
|
||||
float pos[3];
|
||||
GLubyte rgba[4];
|
||||
};
|
||||
|
||||
// Declares supported vertex formats.
|
||||
// Position + Normal.
|
||||
struct VertexPN {
|
||||
float pos[3];
|
||||
float normal[3];
|
||||
};
|
||||
|
||||
// Position + Texture coordinate + Color.
|
||||
struct VertexPTC {
|
||||
float pos[3];
|
||||
float uv[2];
|
||||
GLubyte rgba[4];
|
||||
};
|
||||
|
||||
// Declares Immediate mode types.
|
||||
template <typename _Ty>
|
||||
class GlImmediate;
|
||||
typedef GlImmediate<VertexPC> GlImmediatePC;
|
||||
typedef GlImmediate<VertexPN> GlImmediatePN;
|
||||
typedef GlImmediate<VertexPTC> GlImmediatePTC;
|
||||
|
||||
// GL immedialte mode renderer.
|
||||
// Should be used with a GlImmediate object to push vertices to the renderer.
|
||||
class GlImmediateRenderer {
|
||||
public:
|
||||
GlImmediateRenderer(RendererImpl* _renderer);
|
||||
~GlImmediateRenderer();
|
||||
|
||||
// Initializes immediate mode renderer. Can fail.
|
||||
bool Initialize();
|
||||
|
||||
private:
|
||||
// GlImmediate is used to work with the renderer.
|
||||
template <typename _Ty>
|
||||
friend class GlImmediate;
|
||||
|
||||
// Begin stacking vertices.
|
||||
void Begin();
|
||||
|
||||
// End stacking vertices. Call GL rendering.
|
||||
template <typename _Ty>
|
||||
void End(GLenum _mode, const ozz::math::Float4x4& _transform);
|
||||
|
||||
// Push a new vertex to the buffer.
|
||||
template <typename _Ty>
|
||||
OZZ_INLINE void PushVertex(const _Ty& _vertex) {
|
||||
// Resize buffer if needed.
|
||||
const size_t new_size = size_ + sizeof(_Ty);
|
||||
if (new_size > buffer_.size()) {
|
||||
buffer_.resize(new_size);
|
||||
}
|
||||
|
||||
// Copy this last vertex.
|
||||
std::memcpy(buffer_.data() + size_, &_vertex, sizeof(_Ty));
|
||||
size_ = new_size;
|
||||
}
|
||||
|
||||
// The vertex object used by the renderer.
|
||||
GLuint vbo_;
|
||||
|
||||
// Buffer of vertices.
|
||||
ozz::vector<char> buffer_;
|
||||
|
||||
// Number of vertices.
|
||||
size_t size_;
|
||||
|
||||
// Immediate mode shaders;
|
||||
ozz::unique_ptr<ImmediatePCShader> immediate_pc_shader;
|
||||
ozz::unique_ptr<ImmediatePTCShader> immediate_ptc_shader;
|
||||
|
||||
// The renderer object.
|
||||
RendererImpl* renderer_;
|
||||
};
|
||||
|
||||
// RAII object that allows to push vertices to the imrender stack.
|
||||
template <typename _Ty>
|
||||
class GlImmediate {
|
||||
public:
|
||||
// Immediate object vertex format.
|
||||
typedef _Ty Vertex;
|
||||
|
||||
// Start a new immediate stack.
|
||||
GlImmediate(GlImmediateRenderer* _renderer, GLenum _mode,
|
||||
const ozz::math::Float4x4& _transform)
|
||||
: transform_(_transform), renderer_(_renderer), mode_(_mode) {
|
||||
renderer_->Begin();
|
||||
}
|
||||
|
||||
// End immediate vertex stacking, and renders all vertices.
|
||||
~GlImmediate() { renderer_->End<_Ty>(mode_, transform_); }
|
||||
|
||||
// Pushes a new vertex to the stack.
|
||||
OZZ_INLINE void PushVertex(const _Ty& _vertex) {
|
||||
renderer_->PushVertex(_vertex);
|
||||
}
|
||||
|
||||
private:
|
||||
// Non copyable.
|
||||
GlImmediate(const GlImmediate&);
|
||||
void operator=(const GlImmediate&);
|
||||
|
||||
// Transformation matrix.
|
||||
const ozz::math::Float4x4 transform_;
|
||||
|
||||
// Shared renderer.
|
||||
GlImmediateRenderer* renderer_;
|
||||
|
||||
// Draw array mode GL_POINTS, GL_LINE_STRIP, ...
|
||||
GLenum mode_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_IMMEDIATE_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,332 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_RENDERER_IMPL_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_RENDERER_IMPL_H_
|
||||
|
||||
#ifndef OZZ_INCLUDE_PRIVATE_HEADER
|
||||
#error "This header is private, it cannot be included from public headers."
|
||||
#endif // OZZ_INCLUDE_PRIVATE_HEADER
|
||||
|
||||
// GL and GL ext requires that ptrdif_t is defined on APPLE platforms.
|
||||
#include <cstddef>
|
||||
|
||||
// Don't allow gl.h to automatically include glext.h
|
||||
#define GL_GLEXT_LEGACY
|
||||
|
||||
// Including glfw includes gl.h
|
||||
#include "GL/glfw.h"
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
// include features as core functions.
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#else // EMSCRIPTEN
|
||||
|
||||
// Detects already defined GL_VERSION and deduces required extensions.
|
||||
#ifndef GL_VERSION_1_5
|
||||
#define OZZ_GL_VERSION_1_5_EXT
|
||||
#endif // GL_VERSION_1_5
|
||||
#ifndef GL_VERSION_2_0
|
||||
#define OZZ_GL_VERSION_2_0_EXT
|
||||
#endif // GL_VERSION_2_0
|
||||
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
// Include features as extentions
|
||||
#include "GL/glext.h"
|
||||
|
||||
#include "framework/renderer.h"
|
||||
#include "ozz/base/containers/vector.h"
|
||||
#include "ozz/base/memory/unique_ptr.h"
|
||||
|
||||
// Provides helper macro to test for glGetError on a gl call.
|
||||
#ifndef NDEBUG
|
||||
#define GL(_f) \
|
||||
do { \
|
||||
gl##_f; \
|
||||
GLenum error = glGetError(); \
|
||||
assert(error == GL_NO_ERROR); \
|
||||
\
|
||||
} while (void(0), 0)
|
||||
#else // NDEBUG
|
||||
#define GL(_f) gl##_f
|
||||
#endif // NDEBUG
|
||||
|
||||
// Convenient macro definition for specifying buffer offsets.
|
||||
#define GL_PTR_OFFSET(i) reinterpret_cast<void*>(static_cast<intptr_t>(i))
|
||||
|
||||
namespace ozz {
|
||||
namespace animation {
|
||||
class Skeleton;
|
||||
}
|
||||
namespace math {
|
||||
struct Float4x4;
|
||||
}
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
class Camera;
|
||||
class Shader;
|
||||
class SkeletonShader;
|
||||
class AmbientShader;
|
||||
class AmbientTexturedShader;
|
||||
class AmbientShaderInstanced;
|
||||
class GlImmediateRenderer;
|
||||
|
||||
// Implements Renderer interface.
|
||||
class RendererImpl : public Renderer {
|
||||
public:
|
||||
RendererImpl(Camera* _camera);
|
||||
virtual ~RendererImpl();
|
||||
|
||||
// See Renderer for all the details about the API.
|
||||
virtual bool Initialize();
|
||||
|
||||
virtual bool DrawAxes(const ozz::math::Float4x4& _transform);
|
||||
|
||||
virtual bool DrawGrid(int _cell_count, float _cell_size);
|
||||
|
||||
virtual bool DrawSkeleton(const animation::Skeleton& _skeleton,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
bool _draw_joints);
|
||||
|
||||
virtual bool DrawPosture(const animation::Skeleton& _skeleton,
|
||||
ozz::span<const ozz::math::Float4x4> _matrices,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
bool _draw_joints);
|
||||
|
||||
virtual bool DrawBoxIm(const ozz::math::Box& _box,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
const Color _colors[2]);
|
||||
|
||||
virtual bool DrawBoxShaded(const ozz::math::Box& _box,
|
||||
ozz::span<const ozz::math::Float4x4> _transforms,
|
||||
Color _color);
|
||||
|
||||
virtual bool DrawSphereIm(float _radius,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
const Color _color);
|
||||
|
||||
virtual bool DrawSphereShaded(
|
||||
float _radius, ozz::span<const ozz::math::Float4x4> _transforms,
|
||||
Color _color);
|
||||
|
||||
virtual bool DrawSkinnedMesh(const Mesh& _mesh,
|
||||
const span<math::Float4x4> _skinning_matrices,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
const Options& _options = Options());
|
||||
|
||||
virtual bool DrawMesh(const Mesh& _mesh,
|
||||
const ozz::math::Float4x4& _transform,
|
||||
const Options& _options = Options());
|
||||
|
||||
virtual bool DrawSegment(const math::Float3& _begin, const math::Float3& _end,
|
||||
Color _color, const ozz::math::Float4x4& _transform);
|
||||
|
||||
virtual bool DrawVectors(ozz::span<const float> _positions,
|
||||
size_t _positions_stride,
|
||||
ozz::span<const float> _directions,
|
||||
size_t _directions_stride, int _num_vectors,
|
||||
float _vector_length, Color _color,
|
||||
const ozz::math::Float4x4& _transform);
|
||||
|
||||
virtual bool DrawBinormals(
|
||||
ozz::span<const float> _positions, size_t _positions_stride,
|
||||
ozz::span<const float> _normals, size_t _normals_stride,
|
||||
ozz::span<const float> _tangents, size_t _tangents_stride,
|
||||
ozz::span<const float> _handenesses, size_t _handenesses_stride,
|
||||
int _num_vectors, float _vector_length, Color _color,
|
||||
const ozz::math::Float4x4& _transform);
|
||||
|
||||
// Get GL immediate renderer implementation;
|
||||
GlImmediateRenderer* immediate_renderer() const { return immediate_.get(); }
|
||||
|
||||
// Get application camera that provides rendering matrices.
|
||||
Camera* camera() const { return camera_; }
|
||||
|
||||
private:
|
||||
// Defines the internal structure used to define a model.
|
||||
struct Model {
|
||||
Model();
|
||||
~Model();
|
||||
|
||||
GLuint vbo;
|
||||
GLenum mode;
|
||||
GLsizei count;
|
||||
ozz::unique_ptr<SkeletonShader> shader;
|
||||
};
|
||||
|
||||
// Detects and initializes all OpenGL extension.
|
||||
// Return true if all mandatory extensions were found.
|
||||
bool InitOpenGLExtensions();
|
||||
|
||||
// Initializes posture rendering.
|
||||
// Return true if initialization succeeded.
|
||||
bool InitPostureRendering();
|
||||
|
||||
// Initializes the checkered texture.
|
||||
// Return true if initialization succeeded.
|
||||
bool InitCheckeredTexture();
|
||||
|
||||
// Draw posture internal non-instanced rendering fall back implementation.
|
||||
void DrawPosture_Impl(const ozz::math::Float4x4& _transform,
|
||||
const float* _uniforms, int _instance_count,
|
||||
bool _draw_joints);
|
||||
|
||||
// Draw posture internal instanced rendering implementation.
|
||||
void DrawPosture_InstancedImpl(const ozz::math::Float4x4& _transform,
|
||||
const float* _uniforms, int _instance_count,
|
||||
bool _draw_joints);
|
||||
|
||||
// Array of matrices used to store model space matrices during DrawSkeleton
|
||||
// execution.
|
||||
ozz::vector<ozz::math::Float4x4> prealloc_models_;
|
||||
|
||||
// Application camera that provides rendering matrices.
|
||||
Camera* camera_;
|
||||
|
||||
// Bone and joint model objects.
|
||||
Model models_[2];
|
||||
|
||||
// Dynamic vbo used for arrays.
|
||||
GLuint dynamic_array_bo_;
|
||||
|
||||
// Dynamic vbo used for indices.
|
||||
GLuint dynamic_index_bo_;
|
||||
|
||||
// Volatile memory buffer that can be used within function scope.
|
||||
// Minimum alignment is 16 bytes.
|
||||
class ScratchBuffer {
|
||||
public:
|
||||
ScratchBuffer();
|
||||
~ScratchBuffer();
|
||||
|
||||
// Resizes the buffer to the new size and return the memory address.
|
||||
void* Resize(size_t _size);
|
||||
|
||||
private:
|
||||
void* buffer_;
|
||||
size_t size_;
|
||||
};
|
||||
ScratchBuffer scratch_buffer_;
|
||||
|
||||
// Immediate renderer implementation.
|
||||
ozz::unique_ptr<GlImmediateRenderer> immediate_;
|
||||
|
||||
// Ambient rendering shader.
|
||||
ozz::unique_ptr<AmbientShader> ambient_shader;
|
||||
ozz::unique_ptr<AmbientTexturedShader> ambient_textured_shader;
|
||||
ozz::unique_ptr<AmbientShaderInstanced> ambient_shader_instanced;
|
||||
|
||||
// Checkered texture
|
||||
unsigned int checkered_texture_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
|
||||
// OpenGL 1.5 buffer object management functions, mandatory.
|
||||
#ifdef OZZ_GL_VERSION_1_5_EXT
|
||||
extern PFNGLBINDBUFFERPROC glBindBuffer;
|
||||
extern PFNGLDELETEBUFFERSPROC glDeleteBuffers;
|
||||
extern PFNGLGENBUFFERSPROC glGenBuffers;
|
||||
extern PFNGLISBUFFERPROC glIsBuffer;
|
||||
extern PFNGLBUFFERDATAPROC glBufferData;
|
||||
extern PFNGLBUFFERSUBDATAPROC glBufferSubData;
|
||||
extern PFNGLGETBUFFERSUBDATAPROC glGetBufferSubData;
|
||||
extern PFNGLMAPBUFFERPROC glMapBuffer;
|
||||
extern PFNGLUNMAPBUFFERPROC glUnmapBuffer;
|
||||
extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv;
|
||||
extern PFNGLGETBUFFERPOINTERVPROC glGetBufferPointerv;
|
||||
#endif // OZZ_GL_VERSION_1_5_EXT
|
||||
|
||||
// OpenGL 2.0 shader management functions, mandatory.
|
||||
#ifdef OZZ_GL_VERSION_2_0_EXT
|
||||
extern PFNGLATTACHSHADERPROC glAttachShader;
|
||||
extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation;
|
||||
extern PFNGLCOMPILESHADERPROC glCompileShader;
|
||||
extern PFNGLCREATEPROGRAMPROC glCreateProgram;
|
||||
extern PFNGLCREATESHADERPROC glCreateShader;
|
||||
extern PFNGLDELETEPROGRAMPROC glDeleteProgram;
|
||||
extern PFNGLDELETESHADERPROC glDeleteShader;
|
||||
extern PFNGLDETACHSHADERPROC glDetachShader;
|
||||
extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray;
|
||||
extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray;
|
||||
extern PFNGLGETACTIVEATTRIBPROC glGetActiveAttrib;
|
||||
extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform;
|
||||
extern PFNGLGETATTACHEDSHADERSPROC glGetAttachedShaders;
|
||||
extern PFNGLGETATTRIBLOCATIONPROC glGetAttribLocation;
|
||||
extern PFNGLGETPROGRAMIVPROC glGetProgramiv;
|
||||
extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog;
|
||||
extern PFNGLGETSHADERIVPROC glGetShaderiv;
|
||||
extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog;
|
||||
extern PFNGLGETSHADERSOURCEPROC glGetShaderSource;
|
||||
extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
|
||||
extern PFNGLGETUNIFORMFVPROC glGetUniformfv;
|
||||
extern PFNGLGETUNIFORMIVPROC glGetUniformiv;
|
||||
extern PFNGLGETVERTEXATTRIBDVPROC glGetVertexAttribdv;
|
||||
extern PFNGLGETVERTEXATTRIBFVPROC glGetVertexAttribfv;
|
||||
extern PFNGLGETVERTEXATTRIBIVPROC glGetVertexAttribiv;
|
||||
extern PFNGLGETVERTEXATTRIBPOINTERVPROC glGetVertexAttribPointerv;
|
||||
extern PFNGLISPROGRAMPROC glIsProgram;
|
||||
extern PFNGLISSHADERPROC glIsShader;
|
||||
extern PFNGLLINKPROGRAMPROC glLinkProgram;
|
||||
extern PFNGLSHADERSOURCEPROC glShaderSource;
|
||||
extern PFNGLUSEPROGRAMPROC glUseProgram;
|
||||
extern PFNGLUNIFORM1FPROC glUniform1f;
|
||||
extern PFNGLUNIFORM2FPROC glUniform2f;
|
||||
extern PFNGLUNIFORM3FPROC glUniform3f;
|
||||
extern PFNGLUNIFORM4FPROC glUniform4f;
|
||||
extern PFNGLUNIFORM1IPROC glUniform1i;
|
||||
extern PFNGLUNIFORM2IPROC glUniform2i;
|
||||
extern PFNGLUNIFORM3IPROC glUniform3i;
|
||||
extern PFNGLUNIFORM4IPROC glUniform4i;
|
||||
extern PFNGLUNIFORM1FVPROC glUniform1fv;
|
||||
extern PFNGLUNIFORM2FVPROC glUniform2fv;
|
||||
extern PFNGLUNIFORM3FVPROC glUniform3fv;
|
||||
extern PFNGLUNIFORM4FVPROC glUniform4fv;
|
||||
extern PFNGLUNIFORMMATRIX2FVPROC glUniformMatrix2fv;
|
||||
extern PFNGLUNIFORMMATRIX3FVPROC glUniformMatrix3fv;
|
||||
extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv;
|
||||
extern PFNGLVALIDATEPROGRAMPROC glValidateProgram;
|
||||
extern PFNGLVERTEXATTRIB1FPROC glVertexAttrib1f;
|
||||
extern PFNGLVERTEXATTRIB1FVPROC glVertexAttrib1fv;
|
||||
extern PFNGLVERTEXATTRIB2FPROC glVertexAttrib2f;
|
||||
extern PFNGLVERTEXATTRIB2FVPROC glVertexAttrib2fv;
|
||||
extern PFNGLVERTEXATTRIB3FPROC glVertexAttrib3f;
|
||||
extern PFNGLVERTEXATTRIB3FVPROC glVertexAttrib3fv;
|
||||
extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f;
|
||||
extern PFNGLVERTEXATTRIB4FVPROC glVertexAttrib4fv;
|
||||
extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer;
|
||||
#endif // OZZ_GL_VERSION_2_0_EXT
|
||||
|
||||
// OpenGL ARB_instanced_arrays extension, optional.
|
||||
extern bool GL_ARB_instanced_arrays_supported;
|
||||
extern PFNGLVERTEXATTRIBDIVISORARBPROC glVertexAttribDivisor_;
|
||||
extern PFNGLDRAWARRAYSINSTANCEDARBPROC glDrawArraysInstanced_;
|
||||
extern PFNGLDRAWELEMENTSINSTANCEDARBPROC glDrawElementsInstanced_;
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_RENDERER_IMPL_H_
|
||||
@@ -0,0 +1,766 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define OZZ_INCLUDE_PRIVATE_HEADER // Allows to include private headers.
|
||||
|
||||
#include "shader.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
|
||||
#include "ozz/base/log.h"
|
||||
#include "ozz/base/maths/simd_math.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
// WebGL requires to specify floating point precision
|
||||
static const char* kPlatformSpecivicVSHeader = "precision mediump float;\n";
|
||||
static const char* kPlatformSpecivicFSHeader = "precision mediump float;\n";
|
||||
#else // EMSCRIPTEN
|
||||
static const char* kPlatformSpecivicVSHeader = "";
|
||||
static const char* kPlatformSpecivicFSHeader = "";
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
Shader::Shader() : program_(0), vertex_(0), fragment_(0) {}
|
||||
|
||||
Shader::~Shader() {
|
||||
if (vertex_) {
|
||||
GL(DetachShader(program_, vertex_));
|
||||
GL(DeleteShader(vertex_));
|
||||
}
|
||||
if (fragment_) {
|
||||
GL(DetachShader(program_, fragment_));
|
||||
GL(DeleteShader(fragment_));
|
||||
}
|
||||
if (program_) {
|
||||
GL(DeleteProgram(program_));
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
GLuint CompileShader(GLenum _type, int _count, const char** _src) {
|
||||
GLuint shader = glCreateShader(_type);
|
||||
GL(ShaderSource(shader, _count, _src, nullptr));
|
||||
GL(CompileShader(shader));
|
||||
|
||||
int infolog_length = 0;
|
||||
GL(GetShaderiv(shader, GL_INFO_LOG_LENGTH, &infolog_length));
|
||||
if (infolog_length > 1) {
|
||||
char* info_log = reinterpret_cast<char*>(
|
||||
memory::default_allocator()->Allocate(infolog_length, alignof(char)));
|
||||
int chars_written = 0;
|
||||
glGetShaderInfoLog(shader, infolog_length, &chars_written, info_log);
|
||||
log::Err() << info_log << std::endl;
|
||||
memory::default_allocator()->Deallocate(info_log);
|
||||
}
|
||||
|
||||
int status;
|
||||
GL(GetShaderiv(shader, GL_COMPILE_STATUS, &status));
|
||||
if (status) {
|
||||
return shader;
|
||||
}
|
||||
|
||||
GL(DeleteShader(shader));
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool Shader::BuildFromSource(int _vertex_count, const char** _vertex,
|
||||
int _fragment_count, const char** _fragment) {
|
||||
// Tries to compile shaders.
|
||||
GLuint vertex_shader = 0;
|
||||
if (_vertex) {
|
||||
vertex_shader = CompileShader(GL_VERTEX_SHADER, _vertex_count, _vertex);
|
||||
if (!vertex_shader) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
GLuint fragment_shader = 0;
|
||||
if (_fragment) {
|
||||
fragment_shader =
|
||||
CompileShader(GL_FRAGMENT_SHADER, _fragment_count, _fragment);
|
||||
if (!fragment_shader) {
|
||||
if (vertex_shader) {
|
||||
GL(DeleteShader(vertex_shader));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Shaders are compiled, builds program.
|
||||
program_ = glCreateProgram();
|
||||
vertex_ = vertex_shader;
|
||||
fragment_ = fragment_shader;
|
||||
GL(AttachShader(program_, vertex_shader));
|
||||
GL(AttachShader(program_, fragment_shader));
|
||||
GL(LinkProgram(program_));
|
||||
|
||||
int infolog_length = 0;
|
||||
GL(GetProgramiv(program_, GL_INFO_LOG_LENGTH, &infolog_length));
|
||||
if (infolog_length > 1) {
|
||||
char* info_log = reinterpret_cast<char*>(
|
||||
memory::default_allocator()->Allocate(infolog_length, alignof(char)));
|
||||
int chars_written = 0;
|
||||
glGetProgramInfoLog(program_, infolog_length, &chars_written, info_log);
|
||||
log::Err() << info_log << std::endl;
|
||||
memory::default_allocator()->Deallocate(info_log);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Shader::BindUniform(const char* _semantic) {
|
||||
if (!program_) {
|
||||
return false;
|
||||
}
|
||||
GLint location = glGetUniformLocation(program_, _semantic);
|
||||
if (glGetError() != GL_NO_ERROR || location == -1) { // _semantic not found.
|
||||
return false;
|
||||
}
|
||||
uniforms_.push_back(location);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Shader::FindAttrib(const char* _semantic) {
|
||||
if (!program_) {
|
||||
return false;
|
||||
}
|
||||
GLint location = glGetAttribLocation(program_, _semantic);
|
||||
if (glGetError() != GL_NO_ERROR || location == -1) { // _semantic not found.
|
||||
return false;
|
||||
}
|
||||
attribs_.push_back(location);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shader::UnbindAttribs() {
|
||||
for (size_t i = 0; i < attribs_.size(); ++i) {
|
||||
GL(DisableVertexAttribArray(attribs_[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void Shader::Unbind() {
|
||||
UnbindAttribs();
|
||||
GL(UseProgram(0));
|
||||
}
|
||||
|
||||
ozz::unique_ptr<ImmediatePCShader> ImmediatePCShader::Build() {
|
||||
bool success = true;
|
||||
|
||||
const char* kSimplePCVS =
|
||||
"uniform mat4 u_mvp;\n"
|
||||
"attribute vec3 a_position;\n"
|
||||
"attribute vec4 a_color;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"void main() {\n"
|
||||
" vec4 vertex = vec4(a_position.xyz, 1.);\n"
|
||||
" gl_Position = u_mvp * vertex;\n"
|
||||
" v_vertex_color = a_color;\n"
|
||||
"}\n";
|
||||
const char* kSimplePCPS =
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = v_vertex_color;\n"
|
||||
"}\n";
|
||||
|
||||
const char* vs[] = {kPlatformSpecivicVSHeader, kSimplePCVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kSimplePCPS};
|
||||
|
||||
ozz::unique_ptr<ImmediatePCShader> shader = make_unique<ImmediatePCShader>();
|
||||
success &=
|
||||
shader->BuildFromSource(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
// Binds default attributes
|
||||
success &= shader->FindAttrib("a_position");
|
||||
success &= shader->FindAttrib("a_color");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= shader->BindUniform("u_mvp");
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void ImmediatePCShader::Bind(const math::Float4x4& _model,
|
||||
const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset,
|
||||
GLsizei _color_stride, GLsizei _color_offset) {
|
||||
GL(UseProgram(program()));
|
||||
|
||||
const GLint position_attrib = attrib(0);
|
||||
GL(EnableVertexAttribArray(position_attrib));
|
||||
GL(VertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, _pos_stride,
|
||||
GL_PTR_OFFSET(_pos_offset)));
|
||||
|
||||
const GLint color_attrib = attrib(1);
|
||||
GL(EnableVertexAttribArray(color_attrib));
|
||||
GL(VertexAttribPointer(color_attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
_color_stride, GL_PTR_OFFSET(_color_offset)));
|
||||
|
||||
// Binds mvp uniform
|
||||
const GLint mvp_uniform = uniform(0);
|
||||
const ozz::math::Float4x4 mvp = _view_proj * _model;
|
||||
float values[16];
|
||||
math::StorePtrU(mvp.cols[0], values + 0);
|
||||
math::StorePtrU(mvp.cols[1], values + 4);
|
||||
math::StorePtrU(mvp.cols[2], values + 8);
|
||||
math::StorePtrU(mvp.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mvp_uniform, 1, false, values));
|
||||
}
|
||||
|
||||
ozz::unique_ptr<ImmediatePTCShader> ImmediatePTCShader::Build() {
|
||||
bool success = true;
|
||||
|
||||
const char* kSimplePCVS =
|
||||
"uniform mat4 u_mvp;\n"
|
||||
"attribute vec3 a_position;\n"
|
||||
"attribute vec2 a_tex_coord;\n"
|
||||
"attribute vec4 a_color;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"varying vec2 v_texture_coord;\n"
|
||||
"void main() {\n"
|
||||
" vec4 vertex = vec4(a_position.xyz, 1.);\n"
|
||||
" gl_Position = u_mvp * vertex;\n"
|
||||
" v_vertex_color = a_color;\n"
|
||||
" v_texture_coord = a_tex_coord;\n"
|
||||
"}\n";
|
||||
const char* kSimplePCPS =
|
||||
"uniform sampler2D u_texture;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"varying vec2 v_texture_coord;\n"
|
||||
"void main() {\n"
|
||||
" vec4 tex_color = texture2D(u_texture, v_texture_coord);\n"
|
||||
" gl_FragColor = v_vertex_color * tex_color;\n"
|
||||
" if(gl_FragColor.a < .01) discard;\n" // Implements alpha testing.
|
||||
"}\n";
|
||||
|
||||
const char* vs[] = {kPlatformSpecivicVSHeader, kSimplePCVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kSimplePCPS};
|
||||
|
||||
ozz::unique_ptr<ImmediatePTCShader> shader =
|
||||
make_unique<ImmediatePTCShader>();
|
||||
success &=
|
||||
shader->BuildFromSource(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
// Binds default attributes
|
||||
success &= shader->FindAttrib("a_position");
|
||||
success &= shader->FindAttrib("a_tex_coord");
|
||||
success &= shader->FindAttrib("a_color");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= shader->BindUniform("u_mvp");
|
||||
success &= shader->BindUniform("u_texture");
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void ImmediatePTCShader::Bind(const math::Float4x4& _model,
|
||||
const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset,
|
||||
GLsizei _tex_stride, GLsizei _tex_offset,
|
||||
GLsizei _color_stride, GLsizei _color_offset) {
|
||||
GL(UseProgram(program()));
|
||||
|
||||
const GLint position_attrib = attrib(0);
|
||||
GL(EnableVertexAttribArray(position_attrib));
|
||||
GL(VertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, _pos_stride,
|
||||
GL_PTR_OFFSET(_pos_offset)));
|
||||
|
||||
const GLint tex_attrib = attrib(1);
|
||||
GL(EnableVertexAttribArray(tex_attrib));
|
||||
GL(VertexAttribPointer(tex_attrib, 2, GL_FLOAT, GL_FALSE, _tex_stride,
|
||||
GL_PTR_OFFSET(_tex_offset)));
|
||||
|
||||
const GLint color_attrib = attrib(2);
|
||||
GL(EnableVertexAttribArray(color_attrib));
|
||||
GL(VertexAttribPointer(color_attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
_color_stride, GL_PTR_OFFSET(_color_offset)));
|
||||
|
||||
// Binds mvp uniform
|
||||
const GLint mvp_uniform = uniform(0);
|
||||
const ozz::math::Float4x4 mvp = _view_proj * _model;
|
||||
float values[16];
|
||||
math::StorePtrU(mvp.cols[0], values + 0);
|
||||
math::StorePtrU(mvp.cols[1], values + 4);
|
||||
math::StorePtrU(mvp.cols[2], values + 8);
|
||||
math::StorePtrU(mvp.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mvp_uniform, 1, false, values));
|
||||
|
||||
// Binds texture
|
||||
const GLint texture = uniform(1);
|
||||
GL(Uniform1i(texture, 0));
|
||||
}
|
||||
|
||||
namespace {
|
||||
const char* kPassUv =
|
||||
"attribute vec2 a_uv;\n"
|
||||
"varying vec2 v_vertex_uv;\n"
|
||||
"void PassUv() {\n"
|
||||
" v_vertex_uv = a_uv;\n"
|
||||
"}\n";
|
||||
const char* kPassNoUv =
|
||||
"void PassUv() {\n"
|
||||
"}\n";
|
||||
const char* kShaderUberVS =
|
||||
"uniform mat4 u_mvp;\n"
|
||||
"attribute vec3 a_position;\n"
|
||||
"attribute vec3 a_normal;\n"
|
||||
"attribute vec4 a_color;\n"
|
||||
"varying vec3 v_world_normal;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"void main() {\n"
|
||||
" mat4 world_matrix = GetWorldMatrix();\n"
|
||||
" vec4 vertex = vec4(a_position.xyz, 1.);\n"
|
||||
" gl_Position = u_mvp * world_matrix * vertex;\n"
|
||||
" mat3 cross_matrix = mat3(\n"
|
||||
" cross(world_matrix[1].xyz, world_matrix[2].xyz),\n"
|
||||
" cross(world_matrix[2].xyz, world_matrix[0].xyz),\n"
|
||||
" cross(world_matrix[0].xyz, world_matrix[1].xyz));\n"
|
||||
" float invdet = 1.0 / dot(cross_matrix[2], world_matrix[2].xyz);\n"
|
||||
" mat3 normal_matrix = cross_matrix * invdet;\n"
|
||||
" v_world_normal = normal_matrix * a_normal;\n"
|
||||
" v_vertex_color = a_color;\n"
|
||||
" PassUv();\n"
|
||||
"}\n";
|
||||
const char* kShaderAmbientFct =
|
||||
"vec4 GetAmbient(vec3 _world_normal) {\n"
|
||||
" vec3 normal = normalize(_world_normal);\n"
|
||||
" vec3 alpha = (normal + 1.) * .5;\n"
|
||||
" vec2 bt = mix(vec2(.3, .7), vec2(.4, .8), alpha.xz);\n"
|
||||
" vec3 ambient = mix(vec3(bt.x, .3, bt.x), vec3(bt.y, .8, bt.y), "
|
||||
"alpha.y);\n"
|
||||
" return vec4(ambient, 1.);\n"
|
||||
"}\n";
|
||||
const char* kShaderAmbientFS =
|
||||
"varying vec3 v_world_normal;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"void main() {\n"
|
||||
" vec4 ambient = GetAmbient(v_world_normal);\n"
|
||||
" gl_FragColor = ambient *\n"
|
||||
" v_vertex_color;\n"
|
||||
"}\n";
|
||||
const char* kShaderAmbientTexturedFS =
|
||||
"uniform sampler2D u_texture;\n"
|
||||
"varying vec3 v_world_normal;\n"
|
||||
"varying vec4 v_vertex_color;\n"
|
||||
"varying vec2 v_vertex_uv;\n"
|
||||
"void main() {\n"
|
||||
" vec4 ambient = GetAmbient(v_world_normal);\n"
|
||||
" gl_FragColor = ambient *\n"
|
||||
" v_vertex_color *\n"
|
||||
" texture2D(u_texture, v_vertex_uv);\n"
|
||||
"}\n";
|
||||
} // namespace
|
||||
|
||||
void SkeletonShader::Bind(const math::Float4x4& _model,
|
||||
const math::Float4x4& _view_proj, GLsizei _pos_stride,
|
||||
GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset) {
|
||||
GL(UseProgram(program()));
|
||||
|
||||
const GLint position_attrib = attrib(0);
|
||||
GL(EnableVertexAttribArray(position_attrib));
|
||||
GL(VertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, _pos_stride,
|
||||
GL_PTR_OFFSET(_pos_offset)));
|
||||
|
||||
const GLint normal_attrib = attrib(1);
|
||||
GL(EnableVertexAttribArray(normal_attrib));
|
||||
GL(VertexAttribPointer(normal_attrib, 3, GL_FLOAT, GL_FALSE, _normal_stride,
|
||||
GL_PTR_OFFSET(_normal_offset)));
|
||||
|
||||
const GLint color_attrib = attrib(2);
|
||||
GL(EnableVertexAttribArray(color_attrib));
|
||||
GL(VertexAttribPointer(color_attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
_color_stride, GL_PTR_OFFSET(_color_offset)));
|
||||
|
||||
// Binds mvp uniform
|
||||
const GLint mvp_uniform = uniform(0);
|
||||
const ozz::math::Float4x4 mvp = _view_proj * _model;
|
||||
float values[16];
|
||||
math::StorePtrU(mvp.cols[0], values + 0);
|
||||
math::StorePtrU(mvp.cols[1], values + 4);
|
||||
math::StorePtrU(mvp.cols[2], values + 8);
|
||||
math::StorePtrU(mvp.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mvp_uniform, 1, false, values));
|
||||
}
|
||||
|
||||
ozz::unique_ptr<JointShader> JointShader::Build() {
|
||||
bool success = true;
|
||||
|
||||
const char* vs_joint_to_world_matrix =
|
||||
"mat4 GetWorldMatrix() {\n"
|
||||
" // Rebuilds joint matrix.\n"
|
||||
" mat4 joint_matrix;\n"
|
||||
" joint_matrix[0] = vec4(normalize(joint[0].xyz), 0.);\n"
|
||||
" joint_matrix[1] = vec4(normalize(joint[1].xyz), 0.);\n"
|
||||
" joint_matrix[2] = vec4(normalize(joint[2].xyz), 0.);\n"
|
||||
" joint_matrix[3] = vec4(joint[3].xyz, 1.);\n"
|
||||
|
||||
" // Rebuilds bone properties.\n"
|
||||
" vec3 bone_dir = vec3(joint[0].w, joint[1].w, joint[2].w);\n"
|
||||
" float bone_len = length(bone_dir);\n"
|
||||
|
||||
" // Setup rendering world matrix.\n"
|
||||
" mat4 world_matrix;\n"
|
||||
" world_matrix[0] = joint_matrix[0] * bone_len;\n"
|
||||
" world_matrix[1] = joint_matrix[1] * bone_len;\n"
|
||||
" world_matrix[2] = joint_matrix[2] * bone_len;\n"
|
||||
" world_matrix[3] = joint_matrix[3];\n"
|
||||
" return world_matrix;\n"
|
||||
"}\n";
|
||||
const char* vs[] = {kPlatformSpecivicVSHeader, kPassNoUv,
|
||||
GL_ARB_instanced_arrays_supported
|
||||
? "attribute mat4 joint;\n"
|
||||
: "uniform mat4 joint;\n",
|
||||
vs_joint_to_world_matrix, kShaderUberVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kShaderAmbientFct,
|
||||
kShaderAmbientFS};
|
||||
|
||||
ozz::unique_ptr<JointShader> shader = make_unique<JointShader>();
|
||||
success &=
|
||||
shader->BuildFromSource(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
// Binds default attributes
|
||||
success &= shader->FindAttrib("a_position");
|
||||
success &= shader->FindAttrib("a_normal");
|
||||
success &= shader->FindAttrib("a_color");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= shader->BindUniform("u_mvp");
|
||||
|
||||
if (GL_ARB_instanced_arrays_supported) {
|
||||
success &= shader->FindAttrib("joint");
|
||||
} else {
|
||||
success &= shader->BindUniform("joint");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ozz::unique_ptr<BoneShader>
|
||||
BoneShader::Build() { // Builds a world matrix from joint uniforms,
|
||||
// sticking bone model between
|
||||
bool success = true;
|
||||
|
||||
// parent and child joints.
|
||||
const char* vs_joint_to_world_matrix =
|
||||
"mat4 GetWorldMatrix() {\n"
|
||||
" // Rebuilds bone properties.\n"
|
||||
" // Bone length is set to zero to disable leaf rendering.\n"
|
||||
" float is_bone = joint[3].w;\n"
|
||||
" vec3 bone_dir = vec3(joint[0].w, joint[1].w, joint[2].w) * is_bone;\n"
|
||||
" float bone_len = length(bone_dir);\n"
|
||||
|
||||
" // Setup rendering world matrix.\n"
|
||||
" float dot1 = dot(joint[2].xyz, bone_dir);\n"
|
||||
" float dot2 = dot(joint[0].xyz, bone_dir);\n"
|
||||
" vec3 binormal = abs(dot1) < abs(dot2) ? joint[2].xyz : joint[0].xyz;\n"
|
||||
|
||||
" mat4 world_matrix;\n"
|
||||
" world_matrix[0] = vec4(bone_dir, 0.);\n"
|
||||
" world_matrix[1] = \n"
|
||||
" vec4(bone_len * normalize(cross(binormal, bone_dir)), 0.);\n"
|
||||
" world_matrix[2] =\n"
|
||||
" vec4(bone_len * normalize(cross(bone_dir, world_matrix[1].xyz)), "
|
||||
"0.);\n"
|
||||
" world_matrix[3] = vec4(joint[3].xyz, 1.);\n"
|
||||
" return world_matrix;\n"
|
||||
"}\n";
|
||||
const char* vs[] = {kPlatformSpecivicVSHeader, kPassNoUv,
|
||||
GL_ARB_instanced_arrays_supported
|
||||
? "attribute mat4 joint;\n"
|
||||
: "uniform mat4 joint;\n",
|
||||
vs_joint_to_world_matrix, kShaderUberVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kShaderAmbientFct,
|
||||
kShaderAmbientFS};
|
||||
|
||||
ozz::unique_ptr<BoneShader> shader = make_unique<BoneShader>();
|
||||
success &=
|
||||
shader->BuildFromSource(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
// Binds default attributes
|
||||
success &= shader->FindAttrib("a_position");
|
||||
success &= shader->FindAttrib("a_normal");
|
||||
success &= shader->FindAttrib("a_color");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= shader->BindUniform("u_mvp");
|
||||
|
||||
if (GL_ARB_instanced_arrays_supported) {
|
||||
success &= shader->FindAttrib("joint");
|
||||
} else {
|
||||
success &= shader->BindUniform("joint");
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
ozz::unique_ptr<AmbientShader> AmbientShader::Build() {
|
||||
const char* vs[] = {
|
||||
kPlatformSpecivicVSHeader, kPassNoUv,
|
||||
"uniform mat4 u_mw;\n mat4 GetWorldMatrix() {return u_mw;}\n",
|
||||
kShaderUberVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kShaderAmbientFct,
|
||||
kShaderAmbientFS};
|
||||
|
||||
ozz::unique_ptr<AmbientShader> shader = make_unique<AmbientShader>();
|
||||
bool success =
|
||||
shader->InternalBuild(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
bool AmbientShader::InternalBuild(int _vertex_count, const char** _vertex,
|
||||
int _fragment_count, const char** _fragment) {
|
||||
bool success = true;
|
||||
|
||||
success &=
|
||||
BuildFromSource(_vertex_count, _vertex, _fragment_count, _fragment);
|
||||
|
||||
// Binds default attributes
|
||||
success &= FindAttrib("a_position");
|
||||
success &= FindAttrib("a_normal");
|
||||
success &= FindAttrib("a_color");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= BindUniform("u_mw");
|
||||
success &= BindUniform("u_mvp");
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
void AmbientShader::Bind(const math::Float4x4& _model,
|
||||
const math::Float4x4& _view_proj, GLsizei _pos_stride,
|
||||
GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset) {
|
||||
GL(UseProgram(program()));
|
||||
|
||||
const GLint position_attrib = attrib(0);
|
||||
GL(EnableVertexAttribArray(position_attrib));
|
||||
GL(VertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, _pos_stride,
|
||||
GL_PTR_OFFSET(_pos_offset)));
|
||||
|
||||
const GLint normal_attrib = attrib(1);
|
||||
GL(EnableVertexAttribArray(normal_attrib));
|
||||
GL(VertexAttribPointer(normal_attrib, 3, GL_FLOAT, GL_TRUE, _normal_stride,
|
||||
GL_PTR_OFFSET(_normal_offset)));
|
||||
|
||||
const GLint color_attrib = attrib(2);
|
||||
GL(EnableVertexAttribArray(color_attrib));
|
||||
GL(VertexAttribPointer(color_attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
_color_stride, GL_PTR_OFFSET(_color_offset)));
|
||||
|
||||
// Binds mw uniform
|
||||
float values[16];
|
||||
const GLint mw_uniform = uniform(0);
|
||||
math::StorePtrU(_model.cols[0], values + 0);
|
||||
math::StorePtrU(_model.cols[1], values + 4);
|
||||
math::StorePtrU(_model.cols[2], values + 8);
|
||||
math::StorePtrU(_model.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mw_uniform, 1, false, values));
|
||||
|
||||
// Binds mvp uniform
|
||||
const GLint mvp_uniform = uniform(1);
|
||||
math::StorePtrU(_view_proj.cols[0], values + 0);
|
||||
math::StorePtrU(_view_proj.cols[1], values + 4);
|
||||
math::StorePtrU(_view_proj.cols[2], values + 8);
|
||||
math::StorePtrU(_view_proj.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mvp_uniform, 1, false, values));
|
||||
}
|
||||
|
||||
ozz::unique_ptr<AmbientShaderInstanced> AmbientShaderInstanced::Build() {
|
||||
bool success = true;
|
||||
|
||||
const char* vs[] = {
|
||||
kPlatformSpecivicVSHeader, kPassNoUv,
|
||||
"attribute mat4 a_mw;\n mat4 GetWorldMatrix() {return a_mw;}\n",
|
||||
kShaderUberVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kShaderAmbientFct,
|
||||
kShaderAmbientFS};
|
||||
|
||||
ozz::unique_ptr<AmbientShaderInstanced> shader =
|
||||
make_unique<AmbientShaderInstanced>();
|
||||
success &=
|
||||
shader->BuildFromSource(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
// Binds default attributes
|
||||
success &= shader->FindAttrib("a_position");
|
||||
success &= shader->FindAttrib("a_normal");
|
||||
success &= shader->FindAttrib("a_color");
|
||||
success &= shader->FindAttrib("a_mw");
|
||||
|
||||
// Binds default uniforms
|
||||
success &= shader->BindUniform("u_mvp");
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void AmbientShaderInstanced::Bind(GLsizei _models_offset,
|
||||
const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset,
|
||||
GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset) {
|
||||
GL(UseProgram(program()));
|
||||
|
||||
const GLint position_attrib = attrib(0);
|
||||
GL(EnableVertexAttribArray(position_attrib));
|
||||
GL(VertexAttribPointer(position_attrib, 3, GL_FLOAT, GL_FALSE, _pos_stride,
|
||||
GL_PTR_OFFSET(_pos_offset)));
|
||||
|
||||
const GLint normal_attrib = attrib(1);
|
||||
GL(EnableVertexAttribArray(normal_attrib));
|
||||
GL(VertexAttribPointer(normal_attrib, 3, GL_FLOAT, GL_TRUE, _normal_stride,
|
||||
GL_PTR_OFFSET(_normal_offset)));
|
||||
|
||||
const GLint color_attrib = attrib(2);
|
||||
GL(EnableVertexAttribArray(color_attrib));
|
||||
GL(VertexAttribPointer(color_attrib, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
_color_stride, GL_PTR_OFFSET(_color_offset)));
|
||||
if (_color_stride == 0) {
|
||||
GL(VertexAttribDivisor_(color_attrib,
|
||||
std::numeric_limits<unsigned int>::max()));
|
||||
}
|
||||
|
||||
// Binds mw uniform
|
||||
const GLint models_attrib = attrib(3);
|
||||
GL(EnableVertexAttribArray(models_attrib + 0));
|
||||
GL(EnableVertexAttribArray(models_attrib + 1));
|
||||
GL(EnableVertexAttribArray(models_attrib + 2));
|
||||
GL(EnableVertexAttribArray(models_attrib + 3));
|
||||
GL(VertexAttribDivisor_(models_attrib + 0, 1));
|
||||
GL(VertexAttribDivisor_(models_attrib + 1, 1));
|
||||
GL(VertexAttribDivisor_(models_attrib + 2, 1));
|
||||
GL(VertexAttribDivisor_(models_attrib + 3, 1));
|
||||
GL(VertexAttribPointer(models_attrib + 0, 4, GL_FLOAT, GL_FALSE,
|
||||
sizeof(math::Float4x4),
|
||||
GL_PTR_OFFSET(0 + _models_offset)));
|
||||
GL(VertexAttribPointer(models_attrib + 1, 4, GL_FLOAT, GL_FALSE,
|
||||
sizeof(math::Float4x4),
|
||||
GL_PTR_OFFSET(16 + _models_offset)));
|
||||
GL(VertexAttribPointer(models_attrib + 2, 4, GL_FLOAT, GL_FALSE,
|
||||
sizeof(math::Float4x4),
|
||||
GL_PTR_OFFSET(32 + _models_offset)));
|
||||
GL(VertexAttribPointer(models_attrib + 3, 4, GL_FLOAT, GL_FALSE,
|
||||
sizeof(math::Float4x4),
|
||||
GL_PTR_OFFSET(48 + _models_offset)));
|
||||
|
||||
// Binds mvp uniform
|
||||
const GLint mvp_uniform = uniform(0);
|
||||
float values[16];
|
||||
math::StorePtrU(_view_proj.cols[0], values + 0);
|
||||
math::StorePtrU(_view_proj.cols[1], values + 4);
|
||||
math::StorePtrU(_view_proj.cols[2], values + 8);
|
||||
math::StorePtrU(_view_proj.cols[3], values + 12);
|
||||
GL(UniformMatrix4fv(mvp_uniform, 1, false, values));
|
||||
}
|
||||
|
||||
void AmbientShaderInstanced::Unbind() {
|
||||
const GLint color_attrib = attrib(2);
|
||||
GL(VertexAttribDivisor_(color_attrib, 0));
|
||||
|
||||
const GLint models_attrib = attrib(3);
|
||||
GL(DisableVertexAttribArray(models_attrib + 0));
|
||||
GL(DisableVertexAttribArray(models_attrib + 1));
|
||||
GL(DisableVertexAttribArray(models_attrib + 2));
|
||||
GL(DisableVertexAttribArray(models_attrib + 3));
|
||||
GL(VertexAttribDivisor_(models_attrib + 0, 0));
|
||||
GL(VertexAttribDivisor_(models_attrib + 1, 0));
|
||||
GL(VertexAttribDivisor_(models_attrib + 2, 0));
|
||||
GL(VertexAttribDivisor_(models_attrib + 3, 0));
|
||||
Shader::Unbind();
|
||||
}
|
||||
|
||||
ozz::unique_ptr<AmbientTexturedShader> AmbientTexturedShader::Build() {
|
||||
const char* vs[] = {
|
||||
kPlatformSpecivicVSHeader, kPassUv,
|
||||
"uniform mat4 u_mw;\n mat4 GetWorldMatrix() {return u_mw;}\n",
|
||||
kShaderUberVS};
|
||||
const char* fs[] = {kPlatformSpecivicFSHeader, kShaderAmbientFct,
|
||||
kShaderAmbientTexturedFS};
|
||||
|
||||
ozz::unique_ptr<AmbientTexturedShader> shader =
|
||||
make_unique<AmbientTexturedShader>();
|
||||
bool success =
|
||||
shader->InternalBuild(OZZ_ARRAY_SIZE(vs), vs, OZZ_ARRAY_SIZE(fs), fs);
|
||||
|
||||
success &= shader->FindAttrib("a_uv");
|
||||
|
||||
if (!success) {
|
||||
shader.reset();
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
void AmbientTexturedShader::Bind(const math::Float4x4& _model,
|
||||
const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset,
|
||||
GLsizei _normal_stride, GLsizei _normal_offset,
|
||||
GLsizei _color_stride, GLsizei _color_offset,
|
||||
GLsizei _uv_stride, GLsizei _uv_offset) {
|
||||
AmbientShader::Bind(_model, _view_proj, _pos_stride, _pos_offset,
|
||||
_normal_stride, _normal_offset, _color_stride,
|
||||
_color_offset);
|
||||
|
||||
const GLint uv_attrib = attrib(3);
|
||||
GL(EnableVertexAttribArray(uv_attrib));
|
||||
GL(VertexAttribPointer(uv_attrib, 2, GL_FLOAT, GL_FALSE, _uv_stride,
|
||||
GL_PTR_OFFSET(_uv_offset)));
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
@@ -0,0 +1,249 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHADER_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHADER_H_
|
||||
|
||||
#include "ozz/base/memory/unique_ptr.h"
|
||||
#include "renderer_impl.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace math {
|
||||
struct Float4x4;
|
||||
}
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
// Declares a shader program.
|
||||
class Shader {
|
||||
public:
|
||||
// Construct a fixed function pipeline shader. Use Shader::Build to specify
|
||||
// shader sources.
|
||||
Shader();
|
||||
|
||||
// Destruct a shader.
|
||||
virtual ~Shader();
|
||||
|
||||
// Returns the shader program that can be bound to the OpenGL context.
|
||||
GLuint program() const { return program_; }
|
||||
|
||||
// Request an uniform location and pushes it to the uniform stack.
|
||||
// The uniform location is then accessible thought uniform().
|
||||
bool BindUniform(const char* _semantic);
|
||||
|
||||
// Get an uniform location from the stack at index _index.
|
||||
GLint uniform(int _index) const { return uniforms_[_index]; }
|
||||
|
||||
// Request an attribute location and pushes it to the uniform stack.
|
||||
// The varying location is then accessible thought attrib().
|
||||
bool FindAttrib(const char* _semantic);
|
||||
|
||||
// Get an varying location from the stack at index _index.
|
||||
GLint attrib(int _index) const { return attribs_[_index]; }
|
||||
|
||||
// Unblind shader.
|
||||
virtual void Unbind();
|
||||
|
||||
protected:
|
||||
// Constructs a shader from _vertex and _fragment glsl sources.
|
||||
// Mutliple source files can be specified using the *count argument.
|
||||
bool BuildFromSource(int _vertex_count, const char** _vertex,
|
||||
int _fragment_count, const char** _fragment);
|
||||
|
||||
private:
|
||||
// Unbind all attribs from GL.
|
||||
void UnbindAttribs();
|
||||
|
||||
// Shader program
|
||||
GLuint program_;
|
||||
|
||||
// Vertex and fragment shaders
|
||||
GLuint vertex_;
|
||||
GLuint fragment_;
|
||||
|
||||
// Uniform locations, in the order they were requested.
|
||||
ozz::vector<GLint> uniforms_;
|
||||
|
||||
// Varying locations, in the order they were requested.
|
||||
ozz::vector<GLint> attribs_;
|
||||
};
|
||||
|
||||
class ImmediatePCShader : public Shader {
|
||||
public:
|
||||
ImmediatePCShader() {}
|
||||
virtual ~ImmediatePCShader() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<ImmediatePCShader> Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(const math::Float4x4& _model, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset);
|
||||
};
|
||||
|
||||
class ImmediatePTCShader : public Shader {
|
||||
public:
|
||||
ImmediatePTCShader() {}
|
||||
virtual ~ImmediatePTCShader() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<ImmediatePTCShader> Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(const math::Float4x4& _model, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _tex_stride,
|
||||
GLsizei _tex_offset, GLsizei _color_stride, GLsizei _color_offset);
|
||||
};
|
||||
|
||||
class SkeletonShader : public Shader {
|
||||
public:
|
||||
SkeletonShader() {}
|
||||
virtual ~SkeletonShader() {}
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(const math::Float4x4& _model, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset);
|
||||
|
||||
// Get an attribute location for the join, in cased of instanced rendering.
|
||||
GLint joint_instanced_attrib() const { return attrib(3); }
|
||||
|
||||
// Get an uniform location for the join, in cased of non-instanced rendering.
|
||||
GLint joint_uniform() const { return uniform(1); }
|
||||
};
|
||||
|
||||
class JointShader : public SkeletonShader {
|
||||
public:
|
||||
JointShader() {}
|
||||
virtual ~JointShader() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<JointShader> Build();
|
||||
};
|
||||
|
||||
class BoneShader : public SkeletonShader {
|
||||
public:
|
||||
BoneShader() {}
|
||||
virtual ~BoneShader() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<BoneShader> Build();
|
||||
};
|
||||
|
||||
class AmbientShader : public Shader {
|
||||
public:
|
||||
AmbientShader() {}
|
||||
virtual ~AmbientShader() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<AmbientShader> Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(const math::Float4x4& _model, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset);
|
||||
|
||||
protected:
|
||||
bool InternalBuild(int _vertex_count, const char** _vertex,
|
||||
int _fragment_count, const char** _fragment);
|
||||
};
|
||||
|
||||
class AmbientShaderInstanced : public Shader {
|
||||
public:
|
||||
AmbientShaderInstanced() {}
|
||||
virtual ~AmbientShaderInstanced() {}
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<AmbientShaderInstanced> Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(GLsizei _models_offset, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset);
|
||||
|
||||
virtual void Unbind();
|
||||
};
|
||||
|
||||
class AmbientTexturedShader : public AmbientShader {
|
||||
public:
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static ozz::unique_ptr<AmbientTexturedShader> Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(const math::Float4x4& _model, const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset, GLsizei _normal_stride,
|
||||
GLsizei _normal_offset, GLsizei _color_stride,
|
||||
GLsizei _color_offset, GLsizei _uv_stride, GLsizei _uv_offset);
|
||||
};
|
||||
/*
|
||||
class AmbientTexturedShaderInstanced : public AmbientShaderInstanced {
|
||||
public:
|
||||
|
||||
// Constructs the shader.
|
||||
// Returns nullptr if shader compilation failed or a valid Shader pointer on
|
||||
// success. The shader must then be deleted using default allocator Delete
|
||||
// function.
|
||||
static AmbientTexturedShaderInstanced* Build();
|
||||
|
||||
// Binds the shader.
|
||||
void Bind(GLsizei _models_offset,
|
||||
const math::Float4x4& _view_proj,
|
||||
GLsizei _pos_stride, GLsizei _pos_offset,
|
||||
GLsizei _normal_stride, GLsizei _normal_offset,
|
||||
GLsizei _color_stride, GLsizei _color_offset,
|
||||
GLsizei _uv_stride, GLsizei _uv_offset);
|
||||
};
|
||||
*/
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHADER_H_
|
||||
@@ -0,0 +1,220 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#define OZZ_INCLUDE_PRIVATE_HEADER // Allows to include private headers.
|
||||
|
||||
#include "shooter.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include "renderer_impl.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
Shooter::Shooter()
|
||||
: gl_shot_format_(GL_RGBA), // Default fail safe format and types.
|
||||
image_format_(image::Format::kRGBA),
|
||||
shot_number_(0) {
|
||||
// Test required extension (optional for the framework).
|
||||
// If GL_VERSION_1_5 is defined (aka OZZ_GL_VERSION_1_5_EXT not defined), then
|
||||
// these functions are part of the library (don't need extensions).
|
||||
supported_ = true;
|
||||
#ifdef OZZ_GL_VERSION_1_5_EXT
|
||||
supported_ &= glMapBuffer != nullptr && glUnmapBuffer != nullptr;
|
||||
#endif // OZZ_GL_VERSION_1_5_EXT
|
||||
|
||||
// Initializes shots
|
||||
GLuint pbos[kNumShots];
|
||||
GL(GenBuffers(kNumShots, pbos));
|
||||
for (int i = 0; i < kNumShots; ++i) {
|
||||
Shot& shot = shots_[i];
|
||||
shot.pbo = pbos[i];
|
||||
}
|
||||
|
||||
// OpenGL ES2 compatibility extension allows to query for implementation best
|
||||
// format and type.
|
||||
if (glfwExtensionSupported("GL_ARB_ES2_compatibility") != 0) {
|
||||
GLint format;
|
||||
GL(GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, &format));
|
||||
GLint type;
|
||||
GL(GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, &type));
|
||||
|
||||
// Only support GL_UNSIGNED_BYTE.
|
||||
if (type == GL_UNSIGNED_BYTE) {
|
||||
switch (format) {
|
||||
case GL_RGBA:
|
||||
gl_shot_format_ = format;
|
||||
image_format_ = image::Format::kRGBA;
|
||||
break;
|
||||
case GL_BGRA:
|
||||
gl_shot_format_ = format;
|
||||
image_format_ = image::Format::kBGRA;
|
||||
break;
|
||||
case GL_RGB:
|
||||
gl_shot_format_ = format;
|
||||
image_format_ = image::Format::kRGB;
|
||||
break;
|
||||
case GL_BGR:
|
||||
gl_shot_format_ = format;
|
||||
image_format_ = image::Format::kBGR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Default fail safe format and types.
|
||||
gl_shot_format_ = GL_RGBA;
|
||||
image_format_ = image::Format::kRGBA;
|
||||
}
|
||||
}
|
||||
|
||||
Shooter::~Shooter() {
|
||||
// Process all remaining shots.
|
||||
ProcessAll();
|
||||
|
||||
// Clean shot pbos.
|
||||
for (int i = 0; i < kNumShots; ++i) {
|
||||
Shot& shot = shots_[i];
|
||||
GL(DeleteBuffers(1, &shot.pbo));
|
||||
|
||||
assert(shot.cooldown == 0); // Must have been processed.
|
||||
}
|
||||
}
|
||||
|
||||
void Shooter::Resize(int _width, int _height) {
|
||||
// Early out if not supported.
|
||||
if (!supported_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process all remaining shots.
|
||||
ProcessAll();
|
||||
|
||||
// Resizes all pbos.
|
||||
#ifndef EMSCRIPTEN
|
||||
for (int i = 0; i < kNumShots; ++i) {
|
||||
Shot& shot = shots_[i];
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, shot.pbo));
|
||||
GL(BufferData(GL_PIXEL_PACK_BUFFER, _width * _height * 4, 0,
|
||||
GL_STREAM_READ));
|
||||
shot.width = _width;
|
||||
shot.height = _height;
|
||||
assert(shot.cooldown == 0); // Must have been processed.
|
||||
}
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, 0));
|
||||
#endif // EMSCRIPTEN
|
||||
}
|
||||
|
||||
bool Shooter::Update() { return Process(); }
|
||||
|
||||
bool Shooter::Process() {
|
||||
// Early out if not supported.
|
||||
if (!supported_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Early out if process stack is empty.
|
||||
for (int i = 0; i < kNumShots; ++i) {
|
||||
Shot& shot = shots_[i];
|
||||
|
||||
// Early out for already processed, or empty shots.
|
||||
if (shot.cooldown == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip shots that didn't reached the cooldown.
|
||||
if (--shot.cooldown != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Processes this shot.
|
||||
#ifdef EMSCRIPTEN
|
||||
(void)shot_number_;
|
||||
#else // EMSCRIPTEN
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, shot.pbo));
|
||||
const void* pixels = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
if (pixels) {
|
||||
char name[16];
|
||||
sprintf(name, "%06d.tga", shot_number_++);
|
||||
|
||||
ozz::sample::image::WriteTGA(name, shot.width, shot.height, image_format_,
|
||||
reinterpret_cast<const uint8_t*>(pixels),
|
||||
false);
|
||||
GL(UnmapBuffer(GL_PIXEL_PACK_BUFFER));
|
||||
}
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, 0));
|
||||
#endif // EMSCRIPTEN
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Shooter::ProcessAll() {
|
||||
// Reset cooldown to 1 for all "unprocessed" shots, so they will be
|
||||
// "processed".
|
||||
for (int i = 0; i < kNumShots; ++i) {
|
||||
Shot& shot = shots_[i];
|
||||
shot.cooldown = shot.cooldown > 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
return Process();
|
||||
}
|
||||
|
||||
bool Shooter::Capture(int _buffer) {
|
||||
assert(_buffer == GL_FRONT || _buffer == GL_BACK);
|
||||
|
||||
// Early out if not supported.
|
||||
if (!supported_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Finds the shot to use for this capture.
|
||||
Shot* shot;
|
||||
for (shot = shots_; shot < shots_ + kNumShots && shot->cooldown != 0;
|
||||
++shot) {
|
||||
}
|
||||
assert(shot != shots_ + kNumShots);
|
||||
|
||||
// Initializes cooldown.
|
||||
shot->cooldown = kInitialCountDown;
|
||||
|
||||
#ifndef EMSCRIPTEN
|
||||
// Copy pixels to shot's pbo.
|
||||
GL(ReadBuffer(_buffer));
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, shot->pbo));
|
||||
GL(PixelStorei(GL_PACK_ALIGNMENT, 4));
|
||||
GL(ReadPixels(0, 0, shot->width, shot->height, gl_shot_format_,
|
||||
GL_UNSIGNED_BYTE, 0));
|
||||
GL(BindBuffer(GL_PIXEL_PACK_BUFFER, 0));
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
@@ -0,0 +1,95 @@
|
||||
//----------------------------------------------------------------------------//
|
||||
// //
|
||||
// ozz-animation is hosted at http://github.com/guillaumeblanc/ozz-animation //
|
||||
// and distributed under the MIT License (MIT). //
|
||||
// //
|
||||
// Copyright (c) Guillaume Blanc //
|
||||
// //
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a //
|
||||
// copy of this software and associated documentation files (the "Software"), //
|
||||
// to deal in the Software without restriction, including without limitation //
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, //
|
||||
// and/or sell copies of the Software, and to permit persons to whom the //
|
||||
// Software is furnished to do so, subject to the following conditions: //
|
||||
// //
|
||||
// The above copyright notice and this permission notice shall be included in //
|
||||
// all copies or substantial portions of the Software. //
|
||||
// //
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL //
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING //
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER //
|
||||
// DEALINGS IN THE SOFTWARE. //
|
||||
// //
|
||||
//----------------------------------------------------------------------------//
|
||||
|
||||
#ifndef OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHOOTER_H_
|
||||
#define OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHOOTER_H_
|
||||
|
||||
#include "ozz/base/containers/vector.h"
|
||||
|
||||
#include "framework/image.h"
|
||||
|
||||
namespace ozz {
|
||||
namespace sample {
|
||||
namespace internal {
|
||||
|
||||
// Implements GL screen shot and video shooter
|
||||
class Shooter {
|
||||
public:
|
||||
Shooter();
|
||||
virtual ~Shooter();
|
||||
|
||||
// Resize notification, used to resize memory buffers.
|
||||
void Resize(int _width, int _height);
|
||||
|
||||
// Updates shooter (output captured buffers to memory).
|
||||
bool Update();
|
||||
|
||||
// Captures current (GL_FRONT or GL_BACK) _buffer to memory.
|
||||
bool Capture(int _buffer);
|
||||
|
||||
private:
|
||||
// Updates all cooldowns and process terminated shots. Returns false if it
|
||||
// fails, true on success or empty stack.
|
||||
bool Process();
|
||||
|
||||
// Processes all shots from the stack. Returns false if it fails, true on
|
||||
// success or empty stack.
|
||||
bool ProcessAll();
|
||||
|
||||
// Defines shot buffer (pbo) and data.
|
||||
struct Shot {
|
||||
unsigned int pbo;
|
||||
int width;
|
||||
int height;
|
||||
int cooldown; // Shot is processed when cooldown falls to 0.
|
||||
Shot() : pbo(0), width(0), height(0), cooldown(0) {}
|
||||
};
|
||||
|
||||
// Array of pre-allocated shots, used to allow asynchronous dma transfers of
|
||||
// pbos.
|
||||
enum {
|
||||
kInitialCountDown = 2, // Allows to delay pbo mapping 2 rendering frames.
|
||||
kNumShots = kInitialCountDown,
|
||||
};
|
||||
Shot shots_[kNumShots];
|
||||
|
||||
// Format of pixels to use to glReadPixels calls.
|
||||
int gl_shot_format_;
|
||||
|
||||
// Image format that matches GL format.
|
||||
image::Format::Value image_format_;
|
||||
|
||||
// Shot number, used to name images.
|
||||
int shot_number_;
|
||||
|
||||
// Is the shooter functionality supported.
|
||||
bool supported_;
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace sample
|
||||
} // namespace ozz
|
||||
#endif // OZZ_SAMPLES_FRAMEWORK_INTERNAL_SHOOTER_H_
|
||||
Reference in New Issue
Block a user