mirror of
https://github.com/Relintai/sfw.git
synced 2025-04-14 09:10:47 +02:00
812 lines
25 KiB
C++
812 lines
25 KiB
C++
//--STRIP
|
|
#include "renderer.h"
|
|
|
|
#include "render_core/app_window.h"
|
|
#include "render_core/color_material.h"
|
|
#include "render_core/color_material_2d.h"
|
|
#include "render_core/colored_material.h"
|
|
#include "render_core/font.h"
|
|
#include "render_core/font_material.h"
|
|
#include "render_core/material.h"
|
|
#include "render_core/mesh.h"
|
|
#include "render_core/texture.h"
|
|
#include "render_core/texture_material.h"
|
|
#include "render_core/colored_texture_material_2d.h"
|
|
|
|
#include "render_core/render_state.h"
|
|
//--STRIP
|
|
|
|
bool Renderer::get_depth_buffer_enable() const {
|
|
return _depth_buffer;
|
|
}
|
|
void Renderer::set_depth_buffer_enable(const bool p_depth_buffer) {
|
|
_depth_buffer = p_depth_buffer;
|
|
}
|
|
|
|
Renderer::FaceCulling Renderer::get_face_culling() const {
|
|
return _face_culling;
|
|
}
|
|
void Renderer::set_face_culling(const FaceCulling p_face_culling) {
|
|
if (_face_culling == p_face_culling) {
|
|
return;
|
|
}
|
|
|
|
bool were_disabled = _face_culling == FACE_CULLING_OFF;
|
|
|
|
_face_culling = p_face_culling;
|
|
|
|
switch (p_face_culling) {
|
|
case FACE_CULLING_OFF:
|
|
if (!were_disabled) {
|
|
glDisable(GL_CULL_FACE);
|
|
}
|
|
|
|
break;
|
|
case FACE_CULLING_FRONT:
|
|
if (were_disabled) {
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
|
|
glCullFace(GL_FRONT);
|
|
break;
|
|
case FACE_CULLING_BACK:
|
|
if (were_disabled) {
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
|
|
glCullFace(GL_BACK);
|
|
break;
|
|
case FACE_CULLING_FRONT_AND_BACK:
|
|
if (were_disabled) {
|
|
glEnable(GL_CULL_FACE);
|
|
}
|
|
|
|
glCullFace(GL_FRONT_AND_BACK);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Renderer::draw_point(const Vector2 &p_position, const Color &p_color) {
|
|
//Ugly but oh well
|
|
draw_rect(Rect2(p_position, Vector2(1, 1)), p_color);
|
|
}
|
|
void Renderer::draw_line(const Vector2 &p_from, const Vector2 &p_to, const Color &p_color, const real_t p_width) {
|
|
_2d_mesh->clear();
|
|
|
|
Vector2 offset = (p_from - p_to).rotated(Math_PI / 2.0).normalized();
|
|
offset *= p_width / 2.0;
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_from.x - offset.x, p_from.y - offset.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_to.x + offset.x, p_to.y + offset.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_to.x - offset.x, p_to.y - offset.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_from.x + offset.x, p_from.y + offset.y);
|
|
|
|
//mesh->add_vertex2(-w2, -h2);
|
|
//mesh->add_vertex2(w2, h2);
|
|
//mesh->add_vertex2(-w2, h2);
|
|
//mesh->add_vertex2(w2, -h2);
|
|
|
|
_2d_mesh->add_triangle(1, 0, 2);
|
|
_2d_mesh->add_triangle(0, 1, 3);
|
|
|
|
_2d_mesh->upload();
|
|
|
|
_color_material_2d->bind();
|
|
_2d_mesh->render();
|
|
}
|
|
void Renderer::draw_line_rect(const Rect2 &p_rect, const Color &p_color, const real_t p_width) {
|
|
Vector2 rect_end = p_rect.get_end();
|
|
|
|
//Ugly but oh well
|
|
draw_line(p_rect.position, Vector2(rect_end.x, p_rect.position.y), p_color, p_width);
|
|
draw_line(p_rect.position, Vector2(p_rect.position.x, rect_end.y), p_color, p_width);
|
|
draw_line(rect_end, Vector2(rect_end.x, p_rect.position.y), p_color, p_width);
|
|
draw_line(rect_end, Vector2(p_rect.position.x, rect_end.y), p_color, p_width);
|
|
}
|
|
void Renderer::draw_rect(const Rect2 &p_rect, const Color &p_color) {
|
|
_2d_mesh->clear();
|
|
|
|
Vector2 rect_end = p_rect.get_end();
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_rect.position.x, p_rect.position.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(rect_end.x, rect_end.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(p_rect.position.x, rect_end.y);
|
|
|
|
_2d_mesh->add_color(p_color);
|
|
_2d_mesh->add_vertex2(rect_end.x, p_rect.position.y);
|
|
|
|
_2d_mesh->add_triangle(1, 0, 2);
|
|
_2d_mesh->add_triangle(0, 1, 3);
|
|
|
|
_2d_mesh->upload();
|
|
|
|
_color_material_2d->bind();
|
|
_2d_mesh->render();
|
|
}
|
|
|
|
void Renderer::draw_texture(const Ref<Texture> &p_texture, const Rect2 &p_dst_rect, const Color &p_modulate) {
|
|
_2d_mesh->clear();
|
|
|
|
Vector2 rect_end = p_dst_rect.get_end();
|
|
|
|
_2d_mesh->add_uv(0, 0);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(p_dst_rect.position.x, p_dst_rect.position.y);
|
|
|
|
_2d_mesh->add_uv(1, 1);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(rect_end.x, rect_end.y);
|
|
|
|
_2d_mesh->add_uv(0, 1);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(p_dst_rect.position.x, rect_end.y);
|
|
|
|
_2d_mesh->add_uv(1, 0);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(rect_end.x, p_dst_rect.position.y);
|
|
|
|
_2d_mesh->add_triangle(1, 0, 2);
|
|
_2d_mesh->add_triangle(0, 1, 3);
|
|
|
|
_2d_mesh->upload();
|
|
|
|
_texture_material_2d->texture = p_texture;
|
|
_texture_material_2d->bind();
|
|
_2d_mesh->render();
|
|
}
|
|
void Renderer::draw_texture_clipped(const Ref<Texture> &p_texture, const Rect2 &p_src_rect, const Rect2 &p_dst_rect, const Color &p_modulate) {
|
|
_2d_mesh->clear();
|
|
|
|
Rect2 uv = Rect2(0, 0, 1, 1);
|
|
|
|
if (p_texture.is_valid()) {
|
|
Vector2 ts = p_texture->get_size();
|
|
|
|
Vector2 ss = p_src_rect.position;
|
|
Vector2 se = p_src_rect.get_end();
|
|
|
|
uv.position.x = ss.x / ts.x;
|
|
uv.position.x = ss.y / ts.y;
|
|
uv.size.x = se.x / ts.x;
|
|
uv.size.x = se.y / ts.y;
|
|
}
|
|
|
|
Vector2 rect_end = p_dst_rect.get_end();
|
|
|
|
_2d_mesh->add_uv(uv.position.x, uv.position.y);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(p_dst_rect.position.x, p_dst_rect.position.y);
|
|
|
|
_2d_mesh->add_uv(uv.size.x, uv.size.y);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(rect_end.x, rect_end.y);
|
|
|
|
_2d_mesh->add_uv(uv.position.x, uv.size.y);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(p_dst_rect.position.x, rect_end.y);
|
|
|
|
_2d_mesh->add_uv(uv.size.x, uv.position.y);
|
|
_2d_mesh->add_color(p_modulate);
|
|
_2d_mesh->add_vertex2(rect_end.x, p_dst_rect.position.y);
|
|
|
|
_2d_mesh->add_triangle(1, 0, 2);
|
|
_2d_mesh->add_triangle(0, 1, 3);
|
|
|
|
_2d_mesh->upload();
|
|
|
|
_texture_material_2d->texture = p_texture;
|
|
_texture_material_2d->bind();
|
|
_2d_mesh->render();
|
|
}
|
|
|
|
void Renderer::draw_texture_tr(const Transform2D &p_transform_2d, const Ref<Texture> &p_texture, const Rect2 &p_dst_rect, const Color &p_modulate) {
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
draw_texture(p_texture, p_dst_rect, p_modulate);
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_texture_clipped_tr(const Transform2D &p_transform_2d, const Ref<Texture> &p_texture, const Rect2 &p_src_rect, const Rect2 &p_dst_rect, const Color &p_modulate) {
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
draw_texture_clipped(p_texture, p_src_rect, p_dst_rect, p_modulate);
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
|
|
void Renderer::draw_mesh_2d(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Vector2 &p_position) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
|
|
_texture_material_2d->texture = p_texture;
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_2d_push_model_view_matrix(Transform2D().translated(p_position));
|
|
|
|
_texture_material_2d->bind();
|
|
mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_2d_tr(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Transform2D &p_transform_2d) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
|
|
_texture_material_2d->texture = p_texture;
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
|
|
_texture_material_2d->bind();
|
|
|
|
mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_2d_mat(const Ref<Mesh> &p_mesh, const Ref<Material> &p_material, const Vector2 &p_position) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
ERR_FAIL_COND(!p_material.is_valid());
|
|
|
|
Ref<Material> material = p_material;
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_2d_push_model_view_matrix(Transform2D().translated(p_position));
|
|
|
|
material->bind();
|
|
|
|
mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_2d_mat_tr(const Ref<Mesh> &p_mesh, const Ref<Material> &p_material, const Transform2D &p_transform_2d) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
ERR_FAIL_COND(!p_material.is_valid());
|
|
|
|
Ref<Material> material = p_material;
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
|
|
material->bind();
|
|
|
|
mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
|
|
void Renderer::draw_text_2d(const String &p_text, const Ref<Font> &p_font, const Vector2 &p_position, const Color &p_color) {
|
|
ERR_FAIL_COND(!p_font.is_valid());
|
|
|
|
_font_mesh->clear();
|
|
p_font->generate_mesh(p_text, _font_mesh, p_color);
|
|
_font_mesh->upload();
|
|
|
|
_font_material->texture = p_font->get_texture();
|
|
|
|
camera_2d_push_model_view_matrix(Transform2D().translated(p_position));
|
|
|
|
_font_material->bind();
|
|
|
|
_font_mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_text_2d_tf(const String &p_text, const Ref<Font> &p_font, const Transform2D &p_transform_2d, const Color &p_color) {
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
draw_text_2d(p_text, p_font, Vector2(), p_color);
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_text_2d_tf_material(const String &p_text, const Ref<Font> &p_font, const Ref<Material> &p_material, const Transform2D &p_transform_2d, const Color &p_color) {
|
|
ERR_FAIL_COND(!p_font.is_valid());
|
|
ERR_FAIL_COND(!p_material.is_valid());
|
|
|
|
_font_mesh->clear();
|
|
p_font->generate_mesh(p_text, _font_mesh, p_color);
|
|
_font_mesh->upload();
|
|
|
|
Ref<Material> material = p_material;
|
|
|
|
camera_2d_push_model_view_matrix(p_transform_2d);
|
|
|
|
material->bind();
|
|
|
|
_font_mesh->render();
|
|
camera_2d_pop_model_view_matrix();
|
|
}
|
|
|
|
void Renderer::draw_mesh_3d(const Ref<Mesh> &p_mesh, const Ref<Material> &p_material, const Transform &p_transform) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
ERR_FAIL_COND(!p_material.is_valid());
|
|
|
|
Ref<Mesh> mesh = p_mesh;
|
|
Ref<Material> material = p_material;
|
|
|
|
camera_3d_push_model_view_matrix(p_transform);
|
|
|
|
material->bind();
|
|
mesh->render();
|
|
|
|
camera_3d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_3d_colored(const Ref<Mesh> &p_mesh, const Color &p_color, const Transform &p_transform) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
|
|
Ref<Mesh> mesh = p_mesh;
|
|
_colored_material_3d->color = p_color;
|
|
|
|
camera_3d_push_model_view_matrix(p_transform);
|
|
|
|
_colored_material_3d->bind();
|
|
mesh->render();
|
|
|
|
camera_3d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_3d_vertex_colored(const Ref<Mesh> &p_mesh, const Transform &p_transform) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_3d_push_model_view_matrix(p_transform);
|
|
|
|
_color_material_3d->bind();
|
|
mesh->render();
|
|
|
|
camera_3d_pop_model_view_matrix();
|
|
}
|
|
void Renderer::draw_mesh_3d_textured(const Ref<Mesh> &p_mesh, const Ref<Texture> &p_texture, const Transform &p_transform) {
|
|
ERR_FAIL_COND(!p_mesh.is_valid());
|
|
ERR_FAIL_COND(!p_texture.is_valid());
|
|
|
|
_texture_material_3d->texture = p_texture;
|
|
Ref<Mesh> mesh = p_mesh;
|
|
|
|
camera_3d_push_model_view_matrix(p_transform);
|
|
|
|
_texture_material_3d->bind();
|
|
mesh->render();
|
|
|
|
camera_3d_pop_model_view_matrix();
|
|
}
|
|
|
|
|
|
void Renderer::camera_2d_bind() {
|
|
RenderState::model_view_matrix_2d = _camera_2d_model_view_matrix;
|
|
RenderState::projection_matrix_2d = _camera_2d_projection_matrix;
|
|
}
|
|
void Renderer::camera_2d_reset() {
|
|
RenderState::model_view_matrix_2d = Transform2D();
|
|
RenderState::projection_matrix_2d = Transform();
|
|
|
|
_camera_2d_model_view_matrix_stack.clear();
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
|
|
_camera_2d_projection_matrix = RenderState::projection_matrix_2d;
|
|
_camera_2d_model_view_matrix = RenderState::model_view_matrix_2d;
|
|
}
|
|
|
|
Transform Renderer::camera_2d_get_current_projection_matrix() const {
|
|
return _camera_2d_projection_matrix;
|
|
}
|
|
void Renderer::camera_2d_push_projection_matrix(const Transform &p_transform) {
|
|
_camera_2d_projection_matrix_stack.push_back(_camera_2d_projection_matrix);
|
|
|
|
_camera_2d_projection_matrix *= p_transform;
|
|
|
|
RenderState::projection_matrix_2d = _camera_2d_projection_matrix;
|
|
}
|
|
void Renderer::camera_2d_pop_projection_matrix() {
|
|
if (_camera_2d_projection_matrix_stack.empty()) {
|
|
return;
|
|
}
|
|
|
|
_camera_2d_projection_matrix = _camera_2d_projection_matrix_stack[_camera_2d_projection_matrix_stack.size() - 1];
|
|
|
|
RenderState::projection_matrix_2d = _camera_2d_projection_matrix;
|
|
|
|
_camera_2d_projection_matrix_stack.resize(_camera_2d_projection_matrix_stack.size() - 1);
|
|
}
|
|
int Renderer::get_camera_2d_projection_matrix_stack_size() const {
|
|
return _camera_2d_projection_matrix_stack.size();
|
|
}
|
|
void Renderer::camera_2d_projection_matrix_stack_clear() {
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
|
|
_camera_2d_projection_matrix = Transform();
|
|
RenderState::projection_matrix_2d = _camera_2d_projection_matrix;
|
|
}
|
|
|
|
Transform2D Renderer::camera_2d_get_current_model_view_matrix() const {
|
|
return _camera_2d_model_view_matrix;
|
|
}
|
|
|
|
void Renderer::camera_2d_push_model_view_matrix(const Transform2D &p_transform_2d) {
|
|
_camera_2d_model_view_matrix_stack.push_back(_camera_2d_model_view_matrix);
|
|
|
|
_camera_2d_model_view_matrix *= p_transform_2d;
|
|
|
|
RenderState::model_view_matrix_2d = _camera_2d_model_view_matrix;
|
|
}
|
|
void Renderer::camera_2d_pop_model_view_matrix() {
|
|
if (_camera_2d_model_view_matrix_stack.empty()) {
|
|
return;
|
|
}
|
|
|
|
_camera_2d_model_view_matrix = _camera_2d_model_view_matrix_stack[_camera_2d_model_view_matrix_stack.size() - 1];
|
|
|
|
RenderState::model_view_matrix_2d = _camera_2d_model_view_matrix;
|
|
|
|
_camera_2d_model_view_matrix_stack.resize(_camera_2d_model_view_matrix_stack.size() - 1);
|
|
}
|
|
|
|
int Renderer::get_camera_2d_model_view_matrix_stack_size() const {
|
|
return _camera_2d_model_view_matrix_stack.size();
|
|
}
|
|
void Renderer::camera_2d_model_view_matrix_stack_clear() {
|
|
_camera_2d_model_view_matrix_stack.clear();
|
|
|
|
_camera_2d_model_view_matrix = Transform2D();
|
|
RenderState::model_view_matrix_2d = _camera_2d_model_view_matrix;
|
|
}
|
|
|
|
void Renderer::camera_2d_projection_set_to_window() {
|
|
Vector2 size = get_window_size();
|
|
|
|
Transform canvas_transform;
|
|
canvas_transform.translate_local(-(size.x / 2.0f), -(size.y / 2.0f), 0.0f);
|
|
//canvas_transform.scale(Vector3(2.0f / size.x, 2.0f / size.y, 1.0f));
|
|
canvas_transform.scale(Vector3(2.0f / size.x, -2.0f / size.y, 1.0f));
|
|
|
|
RenderState::projection_matrix_2d = canvas_transform;
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
_camera_2d_projection_matrix = canvas_transform;
|
|
}
|
|
|
|
void Renderer::camera_2d_projection_set_to_size(const Size2i &p_size) {
|
|
Transform canvas_transform;
|
|
canvas_transform.translate_local(-(p_size.x / 2.0f), -(p_size.y / 2.0f), 0.0f);
|
|
//canvas_transform.scale(Vector3(2.0f / size.x, 2.0f / size.y, 1.0f));
|
|
canvas_transform.scale(Vector3(2.0f / p_size.x, -2.0f / p_size.y, 1.0f));
|
|
|
|
RenderState::projection_matrix_2d = canvas_transform;
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
_camera_2d_projection_matrix = canvas_transform;
|
|
}
|
|
|
|
void Renderer::camera_2d_projection_set_to_render_target() {
|
|
Vector2 size = RenderState::render_rect.size;
|
|
|
|
Transform canvas_transform;
|
|
canvas_transform.translate_local(-(size.x / 2.0f), -(size.y / 2.0f), 0.0f);
|
|
//canvas_transform.scale(Vector3(2.0f / size.x, 2.0f / size.y, 1.0f));
|
|
canvas_transform.scale(Vector3(2.0f / size.x, -2.0f / size.y, 1.0f));
|
|
|
|
RenderState::projection_matrix_2d = canvas_transform;
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
_camera_2d_projection_matrix = canvas_transform;
|
|
}
|
|
|
|
void Renderer::camera_2d_projection_set_to_transform(const Transform &p_transform) {
|
|
RenderState::projection_matrix_2d = p_transform;
|
|
_camera_2d_projection_matrix_stack.clear();
|
|
_camera_2d_projection_matrix = p_transform;
|
|
}
|
|
|
|
void Renderer::camera_3d_bind() {
|
|
RenderState::camera_transform_3d = _camera_3d_camera_transform_matrix;
|
|
RenderState::model_view_matrix_3d = _camera_3d_model_view_matrix;
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
}
|
|
|
|
void Renderer::camera_3d_reset() {
|
|
_camera_3d_projection = Projection();
|
|
_camera_3d_camera_transform_matrix = Transform();
|
|
_camera_3d_model_view_matrix = Transform();
|
|
|
|
_camera_3d_camera_transform_matrix_stack.clear();
|
|
_camera_3d_model_view_matrix_stack.clear();
|
|
|
|
RenderState::camera_transform_3d = _camera_3d_camera_transform_matrix;
|
|
RenderState::model_view_matrix_3d = _camera_3d_model_view_matrix;
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
}
|
|
|
|
Transform Renderer::camera_3d_get_current_camera_transform_matrix() const {
|
|
return _camera_3d_camera_transform_matrix;
|
|
}
|
|
void Renderer::camera_3d_push_camera_transform_matrix(const Transform &p_transform) {
|
|
_camera_3d_camera_transform_matrix_stack.push_back(_camera_3d_camera_transform_matrix);
|
|
|
|
_camera_3d_camera_transform_matrix *= p_transform;
|
|
|
|
RenderState::camera_transform_3d = _camera_3d_camera_transform_matrix;
|
|
}
|
|
void Renderer::camera_3d_pop_camera_transform_matrix() {
|
|
if (_camera_3d_camera_transform_matrix_stack.empty()) {
|
|
return;
|
|
}
|
|
|
|
_camera_3d_camera_transform_matrix = _camera_3d_camera_transform_matrix_stack[_camera_3d_camera_transform_matrix_stack.size() - 1];
|
|
|
|
RenderState::camera_transform_3d = _camera_3d_camera_transform_matrix;
|
|
|
|
_camera_3d_camera_transform_matrix_stack.resize(_camera_3d_camera_transform_matrix_stack.size() - 1);
|
|
}
|
|
int Renderer::get_camera_3d_camera_transform_matrix_stack_size() const {
|
|
return _camera_3d_camera_transform_matrix_stack.size();
|
|
}
|
|
|
|
Transform Renderer::camera_3d_get_current_model_view_matrix() const {
|
|
return _camera_3d_model_view_matrix;
|
|
}
|
|
void Renderer::camera_3d_push_model_view_matrix(const Transform &p_transform) {
|
|
_camera_3d_model_view_matrix_stack.push_back(_camera_3d_model_view_matrix);
|
|
|
|
_camera_3d_model_view_matrix *= p_transform;
|
|
|
|
RenderState::model_view_matrix_3d = _camera_3d_model_view_matrix;
|
|
}
|
|
void Renderer::camera_3d_pop_model_view_matrix() {
|
|
if (_camera_3d_model_view_matrix_stack.empty()) {
|
|
return;
|
|
}
|
|
|
|
_camera_3d_model_view_matrix = _camera_3d_model_view_matrix_stack[_camera_3d_model_view_matrix_stack.size() - 1];
|
|
|
|
RenderState::model_view_matrix_3d = _camera_3d_model_view_matrix;
|
|
|
|
_camera_3d_model_view_matrix_stack.resize(_camera_3d_model_view_matrix_stack.size() - 1);
|
|
}
|
|
int Renderer::get_camera_3d_model_view_matrix_stack_size() const {
|
|
return _camera_3d_model_view_matrix_stack.size();
|
|
}
|
|
|
|
// Aspect Ratio = w / h
|
|
void Renderer::camera_3d_projection_set_to_orthographic(float aspect_ratio, float size, float znear, float zfar, bool vaspect) {
|
|
_camera_3d_projection.set_orthogonal(
|
|
size,
|
|
aspect_ratio,
|
|
znear,
|
|
zfar,
|
|
vaspect);
|
|
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
|
|
_last_camera_3d_data.type = LastCamera3DData::TYPE_ORTOGRAPHIC;
|
|
_last_camera_3d_data.size = size;
|
|
_last_camera_3d_data.aspect_ratio = aspect_ratio;
|
|
_last_camera_3d_data.znear = znear;
|
|
_last_camera_3d_data.zfar = zfar;
|
|
_last_camera_3d_data.vaspect = vaspect;
|
|
_last_camera_3d_data.fov = 70;
|
|
_last_camera_3d_data.offset = 0;
|
|
}
|
|
void Renderer::camera_3d_projection_set_to_perspective(float aspect_ratio, float size, float znear, float zfar, bool vaspect, float fov) {
|
|
_camera_3d_projection.set_perspective(
|
|
fov,
|
|
aspect_ratio,
|
|
znear,
|
|
zfar,
|
|
vaspect);
|
|
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
|
|
_last_camera_3d_data.type = LastCamera3DData::TYPE_PERSPECTIVE;
|
|
_last_camera_3d_data.size = size;
|
|
_last_camera_3d_data.aspect_ratio = aspect_ratio;
|
|
_last_camera_3d_data.znear = znear;
|
|
_last_camera_3d_data.zfar = zfar;
|
|
_last_camera_3d_data.vaspect = vaspect;
|
|
_last_camera_3d_data.fov = fov;
|
|
_last_camera_3d_data.offset = 0;
|
|
}
|
|
void Renderer::camera_3d_projection_set_to_frustum(float aspect_ratio, float size, float znear, float zfar, bool vaspect, float offset) {
|
|
_camera_3d_projection.set_frustum(
|
|
size,
|
|
aspect_ratio,
|
|
offset,
|
|
znear,
|
|
zfar,
|
|
vaspect);
|
|
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
|
|
_last_camera_3d_data.type = LastCamera3DData::TYPE_FRUSTUM;
|
|
_last_camera_3d_data.size = size;
|
|
_last_camera_3d_data.aspect_ratio = aspect_ratio;
|
|
_last_camera_3d_data.znear = znear;
|
|
_last_camera_3d_data.zfar = zfar;
|
|
_last_camera_3d_data.vaspect = vaspect;
|
|
_last_camera_3d_data.fov = 70;
|
|
_last_camera_3d_data.offset = offset;
|
|
}
|
|
|
|
Projection Renderer::camera_3d_get_projection_matrix() const {
|
|
return _camera_3d_projection;
|
|
}
|
|
void Renderer::camera_3d_set_projection_matrix(const Projection &p_projection) {
|
|
_camera_3d_projection = p_projection;
|
|
|
|
RenderState::projection_matrix_3d = _camera_3d_projection;
|
|
}
|
|
|
|
Vector3 Renderer::camera_3d_project_ray_normal(const Point2 &p_pos) const {
|
|
Vector3 ray = camera_3d_project_local_ray_normal(p_pos);
|
|
return _camera_3d_camera_transform_matrix.basis.xform(ray).normalized();
|
|
};
|
|
|
|
Vector3 Renderer::camera_3d_project_local_ray_normal(const Point2 &p_pos) const {
|
|
if (_last_camera_3d_data.type == LastCamera3DData::TYPE_ORTOGRAPHIC) {
|
|
return Vector3(0, 0, -1);
|
|
}
|
|
|
|
Size2 viewport_size = RenderState::render_rect.size;
|
|
Vector2 cpos = p_pos;
|
|
Vector3 ray;
|
|
|
|
Projection cm;
|
|
cm.set_perspective(70, viewport_size.aspect(), _last_camera_3d_data.znear, _last_camera_3d_data.zfar, true);
|
|
Vector2 screen_he = cm.get_viewport_half_extents();
|
|
ray = Vector3(((cpos.x / viewport_size.width) * 2.0 - 1.0) * screen_he.x, ((1.0 - (cpos.y / viewport_size.height)) * 2.0 - 1.0) * screen_he.y, -_last_camera_3d_data.znear).normalized();
|
|
|
|
return ray;
|
|
};
|
|
|
|
Vector3 Renderer::camera_3d_project_ray_origin(const Point2 &p_pos) const {
|
|
Size2 viewport_size = RenderState::render_rect.size;
|
|
Vector2 cpos = p_pos;
|
|
ERR_FAIL_COND_V(viewport_size.y == 0, Vector3());
|
|
|
|
Vector2 pos = cpos / viewport_size;
|
|
float vsize, hsize;
|
|
|
|
vsize = _last_camera_3d_data.size / viewport_size.aspect();
|
|
hsize = _last_camera_3d_data.size;
|
|
|
|
Vector3 ray;
|
|
ray.x = pos.x * (hsize)-hsize / 2;
|
|
ray.y = (1.0 - pos.y) * (vsize)-vsize / 2;
|
|
ray.z = -_last_camera_3d_data.znear;
|
|
ray = _camera_3d_camera_transform_matrix.xform(ray);
|
|
return ray;
|
|
};
|
|
|
|
bool Renderer::camera_3d_is_position_behind(const Vector3 &p_pos) const {
|
|
Transform t = _camera_3d_camera_transform_matrix;
|
|
Vector3 eyedir = -t.basis.get_axis(2).normalized();
|
|
return eyedir.dot(p_pos - t.origin) < _last_camera_3d_data.znear;
|
|
}
|
|
|
|
Vector<Vector3> Renderer::camera_3d_get_near_plane_points() const {
|
|
Size2 viewport_size = RenderState::render_rect.size;
|
|
|
|
Projection cm;
|
|
|
|
if (_last_camera_3d_data.type == LastCamera3DData::TYPE_ORTOGRAPHIC) {
|
|
cm.set_orthogonal(_last_camera_3d_data.size, viewport_size.aspect(), _last_camera_3d_data.znear, _last_camera_3d_data.zfar, true);
|
|
} else {
|
|
cm.set_perspective(_last_camera_3d_data.fov, viewport_size.aspect(), _last_camera_3d_data.znear, _last_camera_3d_data.zfar, true);
|
|
}
|
|
|
|
Vector3 endpoints[8];
|
|
cm.get_endpoints(Transform(), endpoints);
|
|
|
|
Vector<Vector3> points;
|
|
points.push_back(Vector3());
|
|
for (int i = 0; i < 4; i++) {
|
|
points.push_back(endpoints[i + 4]);
|
|
}
|
|
return points;
|
|
}
|
|
|
|
Point2 Renderer::camera_3d_unproject_position(const Vector3 &p_pos) const {
|
|
Size2 viewport_size = RenderState::render_rect.size;
|
|
|
|
Projection cm;
|
|
|
|
if (_last_camera_3d_data.type == LastCamera3DData::TYPE_ORTOGRAPHIC) {
|
|
cm.set_orthogonal(_last_camera_3d_data.size, viewport_size.aspect(), _last_camera_3d_data.znear, _last_camera_3d_data.zfar, true);
|
|
} else {
|
|
cm.set_perspective(_last_camera_3d_data.fov, viewport_size.aspect(), _last_camera_3d_data.znear, _last_camera_3d_data.zfar, true);
|
|
}
|
|
|
|
Plane p(_camera_3d_camera_transform_matrix.xform_inv(p_pos), 1.0);
|
|
|
|
p = cm.xform(p);
|
|
p.normal /= p.d;
|
|
|
|
Point2 res;
|
|
res.x = (p.normal.x * 0.5 + 0.5) * viewport_size.x;
|
|
res.y = (-p.normal.y * 0.5 + 0.5) * viewport_size.y;
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
Vector3 Renderer::camera_3d_project_position(const Point2 &p_point, float p_z_depth) const {
|
|
if (p_z_depth == 0) {
|
|
return _camera_3d_camera_transform_matrix.origin;
|
|
}
|
|
|
|
Size2 viewport_size = RenderState::render_rect.size;
|
|
|
|
Projection cm;
|
|
|
|
if (_last_camera_3d_data.type == LastCamera3DData::TYPE_ORTOGRAPHIC) {
|
|
cm.set_orthogonal(_last_camera_3d_data.size, viewport_size.aspect(), p_z_depth, _last_camera_3d_data.zfar, true);
|
|
} else {
|
|
cm.set_perspective(_last_camera_3d_data.fov, viewport_size.aspect(), p_z_depth, _last_camera_3d_data.zfar, true);
|
|
}
|
|
|
|
Vector2 vp_he = cm.get_viewport_half_extents();
|
|
|
|
Vector2 point;
|
|
point.x = (p_point.x / viewport_size.x) * 2.0 - 1.0;
|
|
point.y = (1.0 - (p_point.y / viewport_size.y)) * 2.0 - 1.0;
|
|
point *= vp_he;
|
|
|
|
Vector3 p(point.x, point.y, -p_z_depth);
|
|
|
|
return _camera_3d_camera_transform_matrix.xform(p);
|
|
}
|
|
|
|
|
|
void Renderer::clear_screen(const Color &p_color) {
|
|
glClearColor(p_color.r, p_color.g, p_color.b, p_color.a);
|
|
|
|
if (!_depth_buffer) {
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
} else {
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
}
|
|
}
|
|
|
|
Vector2i Renderer::get_window_size() const {
|
|
return Vector2i(AppWindow::get_singleton()->get_width(), AppWindow::get_singleton()->get_height());
|
|
}
|
|
|
|
float Renderer::get_window_aspect() const {
|
|
return AppWindow::get_singleton()->get_aspect();
|
|
}
|
|
|
|
void Renderer::initialize() {
|
|
ERR_FAIL_COND(_singleton);
|
|
|
|
memnew(Renderer);
|
|
}
|
|
void Renderer::destroy() {
|
|
ERR_FAIL_COND(!_singleton);
|
|
|
|
memdelete(_singleton);
|
|
}
|
|
|
|
Renderer::Renderer() {
|
|
_singleton = this;
|
|
|
|
_depth_buffer = false;
|
|
_face_culling = FACE_CULLING_OFF;
|
|
|
|
_2d_mesh.instance();
|
|
_2d_mesh->vertex_dimesions = 2;
|
|
_3d_mesh.instance();
|
|
_font_mesh.instance();
|
|
_font_mesh->vertex_dimesions = 2;
|
|
|
|
_texture_material_2d.instance();
|
|
_font_material.instance();
|
|
_color_material_2d.instance();
|
|
|
|
_texture_material_3d.instance();
|
|
_color_material_3d.instance();
|
|
_colored_material_3d.instance();
|
|
}
|
|
Renderer::~Renderer() {
|
|
_singleton = NULL;
|
|
}
|
|
|
|
Renderer *Renderer::get_singleton() {
|
|
return _singleton;
|
|
}
|
|
|
|
Renderer *Renderer::_singleton = NULL;
|