awl::main::exit_code const example_main( awl::main::function_context const & ) try { sge::systems::instance< brigand::list< sge::systems::with_window, sge::systems::with_renderer< sge::systems::renderer_caps::core >, sge::systems::with_input > > const sys( sge::systems::make_list ( sge::systems::window( sge::systems::window_source( sge::systems::original_window( sge::window::title( FCPPT_TEXT("sge cg simple test") ) ) ) ) ) ( sge::systems::renderer( sge::renderer::pixel_format::object( sge::renderer::pixel_format::color::depth32, sge::renderer::pixel_format::depth_stencil::off, sge::renderer::pixel_format::optional_multi_samples(), sge::renderer::pixel_format::srgb::no ), sge::renderer::display_mode::parameters( sge::renderer::display_mode::vsync::on, sge::renderer::display_mode::optional_object() ), sge::viewport::optional_resize_callback{ sge::viewport::fill_on_resize() } ) ) ( sge::systems::input( sge::systems::cursor_option_field::null() ) ) ); sge::cg::context::object const cg_context{}; sge::cg::profile::object const vertex_profile( sys.renderer_device_core().create_cg_profile( sge::cg::profile::shader_type::vertex ) ); sge::cg::string const vertex_shader_source( "// This is C2E1v_green from \"The Cg Tutorial\" (Addison-Wesley, ISBN\n" "// 0321194969) by Randima Fernando and Mark J. Kilgard. See page 38.\n" "\n" "struct C2E1v_Output {\n" " float4 position : POSITION;\n" "};\n" "\n" "C2E1v_Output C2E1v_green(float2 position : POSITION)\n" "{\n" " C2E1v_Output OUT;\n" "\n" " OUT.position = float4(position,0,1);\n" "\n" " return OUT;\n" "}\n" ); sge::cg::program::object vertex_program( sge::cg::program::from_string_parameters( cg_context, sge::cg::program::source_type::text, vertex_profile, sge::cg::program::source( vertex_shader_source ), sge::cg::program::main_function( "C2E1v_green" ), sys.renderer_device_core().cg_compile_options( cg_context, vertex_profile ) ) ); sge::renderer::cg::loaded_program_unique_ptr const loaded_vertex_program( sys.renderer_device_core().load_cg_program( vertex_program ) ); sge::cg::profile::object const pixel_profile( sys.renderer_device_core().create_cg_profile( sge::cg::profile::shader_type::pixel ) ); sge::cg::string const pixel_shader_source( "struct C3E3f_Output {\n" " float4 color : COLOR;\n" "};\n" "C3E3f_Output\n" "C3E3f_simple()\n" "{\n" " C3E3f_Output OUT;\n" "\n" " OUT.color = float4(0,1,0,1);\n" " return OUT;\n" "}\n" ); sge::cg::program::object pixel_program( sge::cg::program::from_string_parameters( cg_context, sge::cg::program::source_type::text, pixel_profile, sge::cg::program::source( pixel_shader_source ), sge::cg::program::main_function( "C3E3f_simple" ), sys.renderer_device_core().cg_compile_options( cg_context, pixel_profile ) ) ); sge::renderer::cg::loaded_program_unique_ptr const loaded_pixel_program( sys.renderer_device_core().load_cg_program( pixel_program ) ); typedef sge::renderer::vf::pos< float, 3 > pos3_type; typedef sge::renderer::vf::part< brigand::list< pos3_type > > format_part; typedef sge::renderer::vf::format< brigand::list< format_part > > format; sge::renderer::vertex::declaration_unique_ptr const vertex_declaration( sys.renderer_device_core().create_vertex_declaration( sge::renderer::vertex::declaration_parameters( sge::renderer::vf::dynamic::make_format< format >() ) ) ); sge::renderer::vertex::buffer_unique_ptr const vertex_buffer( sys.renderer_device_core().create_vertex_buffer( sge::renderer::vertex::buffer_parameters( *vertex_declaration, sge::renderer::vf::dynamic::make_part_index< format, format_part >(), sge::renderer::vertex::count( 3u ), sge::renderer::resource_flags_field::null() ) ) ); { sge::renderer::vertex::scoped_lock const vblock( *vertex_buffer, sge::renderer::lock_mode::writeonly ); typedef sge::renderer::vf::view< format_part > vertex_view; vertex_view const vertices( vblock.value() ); vertex_view::iterator vb_it( vertices.begin() ); typedef pos3_type::packed_type vec3; (*vb_it).set< pos3_type >( vec3( -1.f, 1.f, 0.f ) ); ++vb_it; (*vb_it).set< pos3_type >( vec3( -1.f, -1.f, 0.f ) ); ++vb_it; (*vb_it).set< pos3_type >( vec3( 1.f, 1.f, 0.f ) ); } auto const draw( [ &loaded_pixel_program, &loaded_vertex_program, &sys, &vertex_buffer, &vertex_declaration ]{ sge::renderer::context::scoped_core const scoped_block( sys.renderer_device_core(), sys.renderer_device_core().onscreen_target() ); scoped_block.get().clear( sge::renderer::clear::parameters() .back_buffer( sge::image::color::any::object{ sge::image::color::predef::black() } ) ); sge::renderer::vertex::scoped_declaration_and_buffers const vb_context( scoped_block.get(), *vertex_declaration, sge::renderer::vertex::const_buffer_ref_container{ fcppt::make_cref( *vertex_buffer ) } ); sge::renderer::cg::scoped_program const scoped_vertex_program( scoped_block.get(), *loaded_vertex_program ); sge::renderer::cg::scoped_program const scoped_pixel_program( scoped_block.get(), *loaded_pixel_program ); scoped_block.get().render_nonindexed( sge::renderer::vertex::first( 0u ), sge::renderer::vertex::count( 3u ), sge::renderer::primitive_type::triangle_list ); } ); return sge::window::loop( sys.window_system(), sge::window::loop_function{ [ &sys, &draw ]( awl::event::base const &_event ) { sge::systems::quit_on_escape( sys, _event ); fcppt::optional::maybe_void( fcppt::cast::dynamic< sge::renderer::event::render const >( _event ), [ &draw ]( fcppt::reference< sge::renderer::event::render const > ) { draw(); } ); } } ); } catch( fcppt::exception const &_error ) { awl::show_error( _error.string() ); return awl::main::exit_failure(); } catch( std::exception const &_error ) { awl::show_error_narrow( _error.what() ); return awl::main::exit_failure(); }
/** * Shader linker. Currently: * * 1. The last attached vertex shader and fragment shader are linked. * 2. Varying vars in the two shaders are combined so their locations * agree between the vertex and fragment stages. They're treated as * vertex program output attribs and as fragment program input attribs. * 3. The vertex and fragment programs are cloned and modified to update * src/dst register references so they use the new, linked varying * storage locations. */ void _slang_link(GLcontext *ctx, GLhandleARB programObj, struct gl_shader_program *shProg) { const struct gl_vertex_program *vertProg = NULL; const struct gl_fragment_program *fragProg = NULL; GLboolean vertNotify = GL_TRUE, fragNotify = GL_TRUE; GLuint numSamplers = 0; GLuint i; _mesa_clear_shader_program_data(ctx, shProg); /* Initialize LinkStatus to "success". Will be cleared if error. */ shProg->LinkStatus = GL_TRUE; /* check that all programs compiled successfully */ for (i = 0; i < shProg->NumShaders; i++) { if (!shProg->Shaders[i]->CompileStatus) { link_error(shProg, "linking with uncompiled shader\n"); return; } } shProg->Uniforms = _mesa_new_uniform_list(); shProg->Varying = _mesa_new_parameter_list(); /* * Find the vertex and fragment shaders which define main() */ { struct gl_shader *vertShader, *fragShader; vertShader = get_main_shader(ctx, shProg, GL_VERTEX_SHADER); fragShader = get_main_shader(ctx, shProg, GL_FRAGMENT_SHADER); if (vertShader) vertProg = vertex_program(vertShader->Program); if (fragShader) fragProg = fragment_program(fragShader->Program); if (!shProg->LinkStatus) return; } #if FEATURE_es2_glsl /* must have both a vertex and fragment program for ES2 */ if (!vertProg) { link_error(shProg, "missing vertex shader\n"); return; } if (!fragProg) { link_error(shProg, "missing fragment shader\n"); return; } #endif /* * Make copies of the vertex/fragment programs now since we'll be * changing src/dst registers after merging the uniforms and varying vars. */ _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL); if (vertProg) { struct gl_vertex_program *linked_vprog = _mesa_clone_vertex_program(ctx, vertProg); shProg->VertexProgram = linked_vprog; /* refcount OK */ /* vertex program ID not significant; just set Id for debugging purposes */ shProg->VertexProgram->Base.Id = shProg->Name; ASSERT(shProg->VertexProgram->Base.RefCount == 1); } _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL); if (fragProg) { struct gl_fragment_program *linked_fprog = _mesa_clone_fragment_program(ctx, fragProg); shProg->FragmentProgram = linked_fprog; /* refcount OK */ /* vertex program ID not significant; just set Id for debugging purposes */ shProg->FragmentProgram->Base.Id = shProg->Name; ASSERT(shProg->FragmentProgram->Base.RefCount == 1); } /* link varying vars */ if (shProg->VertexProgram) { if (!link_varying_vars(ctx, shProg, &shProg->VertexProgram->Base)) return; } if (shProg->FragmentProgram) { if (!link_varying_vars(ctx, shProg, &shProg->FragmentProgram->Base)) return; } /* link uniform vars */ if (shProg->VertexProgram) { if (!link_uniform_vars(ctx, shProg, &shProg->VertexProgram->Base, &numSamplers)) { return; } } if (shProg->FragmentProgram) { if (!link_uniform_vars(ctx, shProg, &shProg->FragmentProgram->Base, &numSamplers)) { return; } } /*_mesa_print_uniforms(shProg->Uniforms);*/ if (shProg->VertexProgram) { if (!_slang_resolve_attributes(shProg, &vertProg->Base, &shProg->VertexProgram->Base)) { return; } } if (shProg->VertexProgram) { _slang_update_inputs_outputs(&shProg->VertexProgram->Base); _slang_count_temporaries(&shProg->VertexProgram->Base); if (!(shProg->VertexProgram->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_HPOS))) { /* the vertex program did not compute a vertex position */ link_error(shProg, "gl_Position was not written by vertex shader\n"); return; } } if (shProg->FragmentProgram) { _slang_count_temporaries(&shProg->FragmentProgram->Base); _slang_update_inputs_outputs(&shProg->FragmentProgram->Base); } /* Check that all the varying vars needed by the fragment shader are * actually produced by the vertex shader. */ if (shProg->FragmentProgram) { const GLbitfield varyingRead = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0; const GLbitfield64 varyingWritten = shProg->VertexProgram ? shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0; if ((varyingRead & varyingWritten) != varyingRead) { link_error(shProg, "Fragment program using varying vars not written by vertex shader\n"); return; } } /* check that gl_FragColor and gl_FragData are not both written to */ if (shProg->FragmentProgram) { const GLbitfield64 outputsWritten = shProg->FragmentProgram->Base.OutputsWritten; if ((outputsWritten & BITFIELD64_BIT(FRAG_RESULT_COLOR)) && (outputsWritten >= BITFIELD64_BIT(FRAG_RESULT_DATA0))) { link_error(shProg, "Fragment program cannot write both gl_FragColor" " and gl_FragData[].\n"); return; } } if (fragProg && shProg->FragmentProgram) { /* Compute initial program's TexturesUsed info */ _mesa_update_shader_textures_used(&shProg->FragmentProgram->Base); /* notify driver that a new fragment program has been compiled/linked */ vertNotify = ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB, &shProg->FragmentProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { printf("Mesa pre-link fragment program:\n"); _mesa_print_program(&fragProg->Base); _mesa_print_program_parameters(ctx, &fragProg->Base); printf("Mesa post-link fragment program:\n"); _mesa_print_program(&shProg->FragmentProgram->Base); _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base); } } if (vertProg && shProg->VertexProgram) { /* Compute initial program's TexturesUsed info */ _mesa_update_shader_textures_used(&shProg->VertexProgram->Base); /* notify driver that a new vertex program has been compiled/linked */ fragNotify = ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB, &shProg->VertexProgram->Base); if (ctx->Shader.Flags & GLSL_DUMP) { printf("Mesa pre-link vertex program:\n"); _mesa_print_program(&vertProg->Base); _mesa_print_program_parameters(ctx, &vertProg->Base); printf("Mesa post-link vertex program:\n"); _mesa_print_program(&shProg->VertexProgram->Base); _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base); } } /* Debug: */ if (0) { if (shProg->VertexProgram) _mesa_postprocess_program(ctx, &shProg->VertexProgram->Base); if (shProg->FragmentProgram) _mesa_postprocess_program(ctx, &shProg->FragmentProgram->Base); } if (ctx->Shader.Flags & GLSL_DUMP) { printf("Varying vars:\n"); _mesa_print_parameter_list(shProg->Varying); if (shProg->InfoLog) { printf("Info Log: %s\n", shProg->InfoLog); } } if (!vertNotify || !fragNotify) { /* driver rejected one/both of the vertex/fragment programs */ if (!shProg->InfoLog) { link_error(shProg, "Vertex and/or fragment program rejected by driver\n"); } } else { shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram); } }
awl::main::exit_code const example_main( awl::main::function_context const & ) try { sge::systems::instance< brigand::list< sge::systems::with_window, sge::systems::with_renderer< sge::systems::renderer_caps::ffp >, sge::systems::with_input, sge::systems::with_image2d > > const sys( sge::systems::make_list ( sge::systems::window( sge::systems::window_source( sge::systems::original_window( sge::window::title( FCPPT_TEXT("sge cg point sprites test") ) ) ) ) ) ( sge::systems::renderer( sge::renderer::pixel_format::object( sge::renderer::pixel_format::color::depth32, sge::renderer::pixel_format::depth_stencil::off, sge::renderer::pixel_format::optional_multi_samples(), sge::renderer::pixel_format::srgb::no ), sge::renderer::display_mode::parameters( sge::renderer::display_mode::vsync::on, sge::renderer::display_mode::optional_object() ), sge::viewport::optional_resize_callback{ sge::viewport::fill_on_resize() } ) ) ( sge::systems::image2d( sge::media::optional_extension_set( sge::media::extension_set{ sge::media::extension( FCPPT_TEXT("png") ) } ) ) ) ( sge::systems::input( sge::systems::cursor_option_field::null() ) ) ); typedef sge::renderer::vf::pos< float, 3 > pos3_type; typedef sge::renderer::vf::texpos< float, 2, sge::renderer::vf::index< 0u > > texpos_type; typedef sge::renderer::vf::extra< sge::renderer::vf::vector< float, 1u >, sge::renderer::vf::index< 0u > > point_size_type; typedef sge::renderer::vf::part< brigand::list< pos3_type, texpos_type, point_size_type > > format_part; typedef sge::renderer::vf::format< brigand::list< format_part > > format; sge::renderer::vertex::declaration_unique_ptr const vertex_declaration( sys.renderer_device_core().create_vertex_declaration( sge::renderer::vertex::declaration_parameters( sge::renderer::vf::dynamic::make_format< format >() ) ) ); sge::cg::context::object const cg_context; sge::cg::profile::object const vertex_profile( sys.renderer_device_core().create_cg_profile( sge::cg::profile::shader_type::vertex ) ); sge::cg::string const vertex_shader_source( "struct vertex_outputs\n" "{\n" " float2 position : POSITION;\n" " float point_size : PSIZE;\n" " float2 external_texpos : COLOR0;\n" "};\n" "vertex_outputs\n" "vertex_main(\n" " float2 position : POSITION,\n" " float2 texpos : TEXCOORD0,\n" " float point_size : $0$\n" ")\n" "{\n" " vertex_outputs outs;\n" " outs.position = float4(position,0.0,1.0);\n" " outs.point_size = point_size;\n" " outs.external_texpos = texpos;\n" " return outs;\n" "}\n" ); sge::cg::string const pixel_shader_source( "float4\n" "pixel_main(\n" " float2 external_texpos : COLOR0,\n" " float2 texCoord : TEXCOORD0,\n" " uniform sampler2D decal : TEX0\n" ") : COLOR\n" "{\n" " return tex2D(decal,external_texpos.xy + texCoord.xy / 2.0);\n" "}\n" ); sge::cg::program::object vertex_program( sge::cg::program::from_string_parameters( cg_context, sge::cg::program::source_type::text, vertex_profile, sys.renderer_device_core().transform_cg_vertex_program( *vertex_declaration, sge::cg::program::source( vertex_shader_source ) ), sge::cg::program::main_function( "vertex_main" ), sys.renderer_device_core().cg_compile_options( cg_context, vertex_profile ) ) ); sge::renderer::cg::loaded_program_unique_ptr const loaded_vertex_program( sys.renderer_device_core().load_cg_program( vertex_program ) ); sge::cg::profile::object const pixel_profile( sys.renderer_device_core().create_cg_profile( sge::cg::profile::shader_type::pixel ) ); sge::cg::program::object pixel_program( sge::cg::program::from_string_parameters( cg_context, sge::cg::program::source_type::text, pixel_profile, sge::cg::program::source( pixel_shader_source ), sge::cg::program::main_function( "pixel_main" ), sys.renderer_device_core().cg_compile_options( cg_context, pixel_profile ) ) ); sge::renderer::cg::loaded_program_unique_ptr const loaded_pixel_program( sys.renderer_device_core().load_cg_program( pixel_program ) ); sge::renderer::vertex::buffer_unique_ptr const vertex_buffer( sys.renderer_device_core().create_vertex_buffer( sge::renderer::vertex::buffer_parameters( *vertex_declaration, sge::renderer::vf::dynamic::make_part_index< format, format_part >(), sge::renderer::vertex::count( 1u ), sge::renderer::resource_flags_field::null() ) ) ); { sge::renderer::vertex::scoped_lock const vblock( *vertex_buffer, sge::renderer::lock_mode::writeonly ); typedef sge::renderer::vf::view< format_part > vertex_view; vertex_view const vertices( vblock.value() ); vertex_view::iterator vb_it( vertices.begin() ); typedef pos3_type::packed_type pos3; typedef texpos_type::packed_type texpos; typedef point_size_type::packed_type point_size; (*vb_it).set< pos3_type >( pos3( 0.f, 0.f, 0.f ) ); (*vb_it).set< texpos_type >( texpos( 0.5f, 0.5f ) ); (*vb_it).set< point_size_type >( point_size( 200.0f ) ); } sge::renderer::texture::planar_unique_ptr const texture( sge::renderer::texture::create_planar_from_path( sge::config::media_path() / FCPPT_TEXT("images") / FCPPT_TEXT("uvtestgrid.png"), sys.renderer_device_core(), sys.image_system(), sge::renderer::texture::mipmap::off(), sge::renderer::resource_flags_field::null(), sge::renderer::texture::emulate_srgb_from_caps( sys.renderer_device_ffp().caps() ) ) ); sge::renderer::cg::loaded_texture_unique_ptr const loaded_texture( sys.renderer_device_core().load_cg_texture( pixel_program.parameter( "decal" ).object(), *texture ) ); sge::renderer::state::ffp::misc::object_unique_ptr const misc_state( sys.renderer_device_ffp().create_misc_state( sge::renderer::state::ffp::misc::parameters( sge::renderer::state::ffp::misc::enable_point_sprites( true ), sge::renderer::state::ffp::misc::local_viewer( false ), sge::renderer::state::ffp::misc::normalize_normals( false ) ) ) ); auto const draw( [ &loaded_pixel_program, &loaded_texture, &loaded_vertex_program, &misc_state, &sys, &vertex_buffer, &vertex_declaration ]{ sge::renderer::context::scoped_ffp const scoped_block( sys.renderer_device_ffp(), sys.renderer_device_ffp().onscreen_target() ); scoped_block.get().clear( sge::renderer::clear::parameters() .back_buffer( sge::image::color::any::object{ sge::image::color::predef::blue() } ) ); sge::renderer::state::ffp::misc::scoped const scoped_misc( scoped_block.get(), *misc_state ); sge::renderer::vertex::scoped_declaration_and_buffers const vb_context( scoped_block.get(), *vertex_declaration, sge::renderer::vertex::const_buffer_ref_container{ fcppt::make_cref( *vertex_buffer ) } ); sge::renderer::cg::scoped_program const scoped_vertex_program( scoped_block.get(), *loaded_vertex_program ); sge::renderer::cg::scoped_program const scoped_pixel_program( scoped_block.get(), *loaded_pixel_program ); sge::renderer::cg::scoped_texture const scoped_texture( scoped_block.get(), *loaded_texture ); scoped_block.get().render_nonindexed( sge::renderer::vertex::first( 0u ), sge::renderer::vertex::count{ vertex_buffer->linear_size() }, sge::renderer::primitive_type::point_list ); } ); return sge::window::loop( sys.window_system(), sge::window::loop_function{ [ &sys, &draw ]( awl::event::base const &_event ) { sge::systems::quit_on_escape( sys, _event ); fcppt::optional::maybe_void( fcppt::cast::dynamic< sge::renderer::event::render const >( _event ), [ &draw ]( fcppt::reference< sge::renderer::event::render const > ) { draw(); } ); } } ); } catch( fcppt::exception const &_error ) { awl::show_error( _error.string() ); return awl::main::exit_failure(); } catch( std::exception const &_error ) { awl::show_error_narrow( _error.what() ); return awl::main::exit_failure(); }