Jelajahi Sumber

Always render offscreen

Daniele Bartolini 8 tahun lalu
induk
melakukan
4606197a57

+ 46 - 0
samples/core/shaders/default.shader

@@ -274,6 +274,44 @@ bgfx_shaders = {
 			}
 		"""
 	}
+
+	blit = {
+		includes = "common"
+
+		varying = """
+			vec2 v_texcoord0 : TEXCOORD0 = vec2(0.0, 0.0);
+
+			vec3 a_position  : POSITION;
+			vec2 a_texcoord0 : TEXCOORD0;
+		"""
+
+		vs_input_output = """
+			$input a_position, a_texcoord0
+			$output v_texcoord0
+		"""
+
+		vs_code = """
+			void main()
+			{
+				gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0) );
+				v_texcoord0 = a_texcoord0;
+			}
+		"""
+
+		fs_input_output = """
+			$input v_texcoord0
+		"""
+
+		fs_code = """
+			SAMPLER2D(s_texColor, 0);
+
+			void main()
+			{
+				gl_FragColor = texture2D(s_texColor, v_texcoord0);
+			}
+		"""
+	}
+
 }
 
 shaders = {
@@ -301,6 +339,12 @@ shaders = {
 		bgfx_shader = "mesh"
 		render_state = "mesh"
 	}
+
+	blit = {
+		bgfx_shader = "blit"
+		render_state = "gui"
+	}
+
 }
 
 static_compile = [
@@ -312,4 +356,6 @@ static_compile = [
 	{ shader = "mesh" defines = [] }
 	{ shader = "mesh" defines = ["DIFFUSE_MAP"] }
 	{ shader = "mesh" defines = ["DIFFUSE_MAP" "NO_LIGHT"] }
+	{ shader = "blit" defines = [] }
+
 ]

+ 32 - 7
src/device/device.cpp

@@ -213,6 +213,7 @@ Device::Device(const DeviceOptions& opts, ConsoleServer& cs)
 	, _input_manager(NULL)
 	, _unit_manager(NULL)
 	, _lua_environment(NULL)
+	, _pipeline(NULL)
 	, _display(NULL)
 	, _window(NULL)
 	, _worlds(default_allocator())
@@ -230,7 +231,7 @@ bool Device::process_events(bool vsync)
 	bool reset = false;
 
 	OsEvent event;
-	while(next_event(event))
+	while (next_event(event))
 	{
 		if (event.type == OsEventType::NONE)
 			continue;
@@ -453,11 +454,16 @@ void Device::run()
 	_lua_environment->execute_string(_device_options._lua_string.c_str());
 	_lua_environment->execute((LuaResource*)_resource_manager->get(RESOURCE_TYPE_SCRIPT, _boot_config.boot_script_name));
 
+	_pipeline = CE_NEW(_allocator, Pipeline)();
+	_pipeline->create(_width, _height);
+
 	logi(DEVICE, "Initialized");
 
 	_lua_environment->call_global("init", 0);
 
 	s64 time_last = os::clocktime();
+	u16 old_width = 0;
+	u16 old_height = 0;
 
 	while (!process_events(_boot_config.vsync) && !_quit)
 	{
@@ -472,6 +478,13 @@ void Device::run()
 		RECORD_FLOAT("device.dt", dt);
 		RECORD_FLOAT("device.fps", 1.0f/dt);
 
+		if (_width != old_width || _height != old_height)
+		{
+			old_width = _width;
+			old_height = _height;
+			_pipeline->reset(_width, _height);
+		}
+
 		if (!_paused)
 		{
 			_resource_manager->complete_requests();
@@ -508,6 +521,7 @@ void Device::run()
 	physics_globals::shutdown(_allocator);
 	audio_globals::shutdown();
 
+	CE_DELETE(_allocator, _pipeline);
 	CE_DELETE(_allocator, _lua_environment);
 	CE_DELETE(_allocator, _unit_manager);
 	CE_DELETE(_allocator, _input_manager);
@@ -516,6 +530,8 @@ void Device::run()
 	CE_DELETE(_allocator, _resource_manager);
 	CE_DELETE(_allocator, _resource_loader);
 
+	_pipeline->destroy();
+
 	bgfx::shutdown();
 	_window->close();
 	window::destroy(_allocator, *_window);
@@ -571,12 +587,7 @@ void Device::render(World& world, UnitId camera_unit)
 	Matrix4x4 ortho_proj;
 	orthographic(ortho_proj, 0, _width, 0, _height, 0.01f, 1.0f);
 
-	bgfx::setViewClear(0
-		, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH
-		, 0x353839ff
-		, 1.0f
-		, 0
-		);
+	bgfx::setViewClear(VIEW_SPRITE_0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x353839ff, 1.0f, 0);
 
 	bgfx::setViewTransform(VIEW_SPRITE_0, to_float_ptr(view), to_float_ptr(proj));
 	bgfx::setViewTransform(VIEW_SPRITE_1, to_float_ptr(view), to_float_ptr(proj));
@@ -612,6 +623,18 @@ void Device::render(World& world, UnitId camera_unit)
 	bgfx::setViewMode(VIEW_SPRITE_7, bgfx::ViewMode::DepthAscending);
 	bgfx::setViewMode(VIEW_GUI, bgfx::ViewMode::Sequential);
 
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_0, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_1, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_2, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_3, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_4, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_5, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_6, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_SPRITE_7, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_MESH, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_DEBUG, _pipeline->_frame_buffer);
+	bgfx::setViewFrameBuffer(VIEW_GUI, _pipeline->_frame_buffer);
+
 	bgfx::touch(VIEW_SPRITE_0);
 	bgfx::touch(VIEW_SPRITE_1);
 	bgfx::touch(VIEW_SPRITE_2);
@@ -625,6 +648,8 @@ void Device::render(World& world, UnitId camera_unit)
 	bgfx::touch(VIEW_GUI);
 
 	world.render(view, proj);
+
+	_pipeline->render(*_shader_manager, StringId32("blit"), 0, _width, _height);
 }
 
 World* Device::create_world()

+ 2 - 0
src/device/device.h

@@ -17,6 +17,7 @@
 #include "device/device_options.h"
 #include "device/display.h"
 #include "device/input_types.h"
+#include "device/pipeline.h"
 #include "device/window.h"
 #include "lua/types.h"
 #include "resource/types.h"
@@ -51,6 +52,7 @@ struct Device
 	InputManager* _input_manager;
 	UnitManager* _unit_manager;
 	LuaEnvironment* _lua_environment;
+	Pipeline* _pipeline;
 	Display* _display;
 	Window* _window;
 	Array<World*> _worlds;

+ 181 - 0
src/device/pipeline.cpp

@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2012-2017 Daniele Bartolini and individual contributors.
+ * License: https://github.com/dbartolini/crown/blob/master/LICENSE
+ */
+
+#include "core/types.h"
+#include "device/pipeline.h"
+#include "world/shader_manager.h"
+#include <bx/math.h>
+
+namespace crown
+{
+/*
+ * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+struct PosTexCoord0Vertex
+{
+	float m_x;
+	float m_y;
+	float m_z;
+	float m_u;
+	float m_v;
+
+	static void init()
+	{
+		ms_decl
+			.begin()
+			.add(bgfx::Attrib::Position,  3, bgfx::AttribType::Float)
+			.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
+			.end();
+	}
+
+	static bgfx::VertexDecl ms_decl;
+};
+
+bgfx::VertexDecl PosTexCoord0Vertex::ms_decl;
+
+/*
+ * Copyright 2011-2017 Branimir Karadzic. All rights reserved.
+ * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
+ */
+void screenSpaceQuad(float _textureWidth, float _textureHeight, float _texelHalf, bool _originBottomLeft, float _width = 1.0f, float _height = 1.0f)
+{
+	if (3 == bgfx::getAvailTransientVertexBuffer(3, PosTexCoord0Vertex::ms_decl) )
+	{
+		bgfx::TransientVertexBuffer vb;
+		bgfx::allocTransientVertexBuffer(&vb, 3, PosTexCoord0Vertex::ms_decl);
+		PosTexCoord0Vertex* vertex = (PosTexCoord0Vertex*)vb.data;
+
+		const float minx = -_width;
+		const float maxx =  _width;
+		const float miny = 0.0f;
+		const float maxy = _height*2.0f;
+
+		const float texelHalfW = _texelHalf/_textureWidth;
+		const float texelHalfH = _texelHalf/_textureHeight;
+		const float minu = -1.0f + texelHalfW;
+		const float maxu =  1.0f + texelHalfH;
+
+		const float zz = 0.0f;
+
+		float minv = texelHalfH;
+		float maxv = 2.0f + texelHalfH;
+
+		if (_originBottomLeft)
+		{
+			float temp = minv;
+			minv = maxv;
+			maxv = temp;
+
+			minv -= 1.0f;
+			maxv -= 1.0f;
+		}
+
+		vertex[0].m_x = minx;
+		vertex[0].m_y = miny;
+		vertex[0].m_z = zz;
+		vertex[0].m_u = minu;
+		vertex[0].m_v = minv;
+
+		vertex[1].m_x = maxx;
+		vertex[1].m_y = miny;
+		vertex[1].m_z = zz;
+		vertex[1].m_u = maxu;
+		vertex[1].m_v = minv;
+
+		vertex[2].m_x = maxx;
+		vertex[2].m_y = maxy;
+		vertex[2].m_z = zz;
+		vertex[2].m_u = maxu;
+		vertex[2].m_v = maxv;
+
+		bgfx::setVertexBuffer(0, &vb);
+	}
+}
+
+Pipeline::Pipeline()
+	: _frame_buffer(BGFX_INVALID_HANDLE)
+{
+	for (u32 i = 0; i < countof(_buffers); ++i)
+		_buffers[i] = BGFX_INVALID_HANDLE;
+}
+
+void Pipeline::create(uint16_t width, uint16_t height)
+{
+	PosTexCoord0Vertex::init();
+	_tex_color = bgfx::createUniform("s_texColor",  bgfx::UniformType::Int1);
+
+	reset(width, height);
+}
+
+void Pipeline::destroy()
+{
+	bgfx::destroy(_frame_buffer);
+	bgfx::destroy(_buffers[1]);
+	bgfx::destroy(_buffers[0]);
+	bgfx::destroy(_tex_color);
+}
+
+void Pipeline::reset(u16 width, u16 height)
+{
+	for (u32 i = 0; i < countof(_buffers); ++i)
+	{
+		if (bgfx::isValid(_buffers[i]))
+			bgfx::destroy(_buffers[i]);
+	}
+
+	_buffers[0] = bgfx::createTexture2D(width
+		, height
+		, false
+		, 1
+		, bgfx::TextureFormat::BGRA8
+		, BGFX_TEXTURE_RT
+		);
+	_buffers[1] = bgfx::createTexture2D(width
+		, height
+		, false
+		, 1
+		, bgfx::TextureFormat::D24S8
+		, BGFX_TEXTURE_RT
+		);
+
+	if (bgfx::isValid(_frame_buffer))
+		bgfx::destroy(_frame_buffer);
+
+	_frame_buffer = bgfx::createFrameBuffer(countof(_buffers), _buffers);
+}
+
+void Pipeline::render(ShaderManager& sm, StringId32 program, uint8_t view, uint16_t width, uint16_t height)
+{
+	const bgfx::Caps* caps = bgfx::getCaps();
+
+	f32 ortho[16];
+	bx::mtxOrtho(ortho, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f, 0.0f, caps->homogeneousDepth);
+
+	bgfx::setViewClear(view
+		, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH | BGFX_CLEAR_STENCIL
+		, 0x353839ff
+		, 1.0f
+		, 0
+		);
+
+	bgfx::setViewFrameBuffer(view, BGFX_INVALID_HANDLE);
+	bgfx::setViewRect(view, 0, 0, width, height);
+	bgfx::setViewTransform(view, NULL, ortho);
+
+	const uint32_t samplerFlags = 0
+		| BGFX_TEXTURE_RT
+		| BGFX_TEXTURE_MIN_POINT
+		| BGFX_TEXTURE_MAG_POINT
+		| BGFX_TEXTURE_MIP_POINT
+		| BGFX_TEXTURE_U_CLAMP
+		| BGFX_TEXTURE_V_CLAMP
+		;
+	bgfx::setTexture(0, _tex_color, _buffers[0], samplerFlags);
+	screenSpaceQuad(width, height, 0.0f, caps->originBottomLeft);
+	sm.submit(program, view, 0, BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE);
+}
+
+} // namespace crown

+ 36 - 8
src/device/pipeline.h

@@ -5,14 +5,42 @@
 
 #pragma once
 
-#define VIEW_SPRITE_0   0
-#define VIEW_SPRITE_1   1
-#define VIEW_SPRITE_2   2
-#define VIEW_SPRITE_3   3
-#define VIEW_SPRITE_4   4
-#define VIEW_SPRITE_5   5
-#define VIEW_SPRITE_6   6
-#define VIEW_SPRITE_7   7
+#include "world/types.h"
+#include <bgfx/bgfx.h>
+
+#define VIEW_SPRITE_0   1
+#define VIEW_SPRITE_1   2
+#define VIEW_SPRITE_2   3
+#define VIEW_SPRITE_3   4
+#define VIEW_SPRITE_4   5
+#define VIEW_SPRITE_5   6
+#define VIEW_SPRITE_6   7
+#define VIEW_SPRITE_7   8
 #define VIEW_MESH      16
 #define VIEW_DEBUG     17
 #define VIEW_GUI      128
+
+namespace crown
+{
+struct Pipeline
+{
+	bgfx::TextureHandle _buffers[2];
+	bgfx::FrameBufferHandle _frame_buffer;
+	bgfx::UniformHandle _tex_color;
+
+	Pipeline();
+
+	///
+	void create(uint16_t width, uint16_t height);
+
+	///
+	void destroy();
+
+	///
+	void reset(u16 width, u16 height);
+
+	///
+	void render(ShaderManager& sm, StringId32 program, uint8_t view, uint16_t width, uint16_t height);
+};
+
+} // namespace crown