Jump to content
  • Advertisement

Search the Community

Showing results for tags '3D'.



More search options

  • Search By Tags

    Type tags separated by commas.
  • Search By Author

Content Type


Categories

  • Audio
    • Music and Sound FX
  • Business
    • Business and Law
    • Career Development
    • Production and Management
  • Game Design
    • Game Design and Theory
    • Writing for Games
    • UX for Games
  • Industry
    • Interviews
    • Event Coverage
  • Programming
    • Artificial Intelligence
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Engines and Middleware
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
  • Archive

Categories

  • News

Categories

  • Audio
  • Visual Arts
  • Programming
  • Writing

Categories

  • GameDev Unboxed

Categories

  • Game Dev Loadout
  • Game Dev Unchained

Categories

  • Game Developers Conference
    • GDC 2017
    • GDC 2018
  • Power-Up Digital Games Conference
    • PDGC I: Words of Wisdom
    • PDGC II: The Devs Strike Back
    • PDGC III: Syntax Error

Forums

  • Audio
    • Music and Sound FX
  • Business
    • Games Career Development
    • Production and Management
    • Games Business and Law
  • Game Design
    • Game Design and Theory
    • Writing for Games
  • Programming
    • Artificial Intelligence
    • Engines and Middleware
    • General and Gameplay Programming
    • Graphics and GPU Programming
    • Math and Physics
    • Networking and Multiplayer
  • Visual Arts
    • 2D and 3D Art
    • Critique and Feedback
  • Community
    • GameDev Challenges
    • GDNet+ Member Forum
    • GDNet Lounge
    • GDNet Comments, Suggestions, and Ideas
    • Coding Horrors
    • Your Announcements
    • Hobby Project Classifieds
    • Indie Showcase
    • Article Writing
  • Affiliates
    • NeHe Productions
    • AngelCode
  • Topical
    • Virtual and Augmented Reality
    • News
  • Workshops
    • C# Workshop
    • CPP Workshop
    • Freehand Drawing Workshop
    • Hands-On Interactive Game Development
    • SICP Workshop
    • XNA 4.0 Workshop
  • Archive
    • Topical
    • Affiliates
    • Contests
    • Technical
  • GameDev Challenges's Topics
  • For Beginners's Forum

Calendars

  • Community Calendar
  • Games Industry Events
  • Game Jams
  • GameDev Challenges's Schedule

Blogs

There are no results to display.

There are no results to display.

Product Groups

  • Advertisements
  • GameDev Gear

Developers

Developers


Find results in...

Find results that contain...


Date Created

  • Start

    End


Last Updated

  • Start

    End


Filter by number of...

Joined

  • Start

    End


Group


About Me


Website


Role


Twitter


Github


Twitch


Steam

Found 1000 results

  1. I need help, I just started learning today (about programming). But I dont understand what I am doing wrong I am getting a error message: Assets/PlayerMovement.cs(10,9): error CS0117: UnityEngine.Debug' does not contain a definition forlog' I found the problem (its about the captials.)
  2. jbadams

    Free art assets

    The older version of this topic is getting quite dated, with some broken links and notable omissions, so after 8 years it's high time for an update. This is a list of free graphics for games but aims to avoid sprites ripped from existing games in favour of ones that may be legally used in your work. Please feel free to submit your own suggestions, but note that any off-topic posts and all spam may be removed from this topic. Be sure to check the licensing terms before using any of the linked graphics. Free Airplane Sprite Pack A free .zip package right here on GameDev.net containing various aircraft from different (mostly side or top down) angles. Includes fighter jets, bombers and cargo planes. Provided by our very own (but recently inactive) @Prinz Eugn (Mark Simpson). Free for any use with attribution to the author. Kenney Assets A huge collection of freely available assets (both 2d and 3d) for many different styles of games, available under CC0 1.0 Universal licensing terms. In addition to the free assets, Kenney's work is supported by the sale of cheaply available asset packs which you'll find linked at the top of the page, and the fantastic Asset Forge which allows the easy creation of customised game assets. SpriteLib GPL A free .zip package of 2d games sprites by Ari Feldman, now available under a Common Public License Version 1.0. Unfortunately, the original website is no longer online, the source website is back online HERE, but the sprite package is attached to this post for you to download: spritelib_gpl.zip Contains sprites for a platform game, Pong/Breakout/Arkanoid style games, overhead shooter in the style of 1943, and a maze combat game in the style of Tank Force. Lost Garden Freely provided graphics from Daniel Cook of Lost Garden & Spry Fox, under licensing terms explained on this page. Danc's Miraculously Flexible Game Prototyping Tiles Danc's Miraculously Flexible Game Prototyping Graphics for Small Worlds 250 free hand-drawn textures Tyrian ships and tiles Tiles for Zelda-like RPG Complete set of 8-bit Sinistar clone graphics Unreleased RTS Postmortem: 'Hard Vacuum' (graphics near end of post) In addition to the above, Daniel also has a couple of 'Game Prototyping Challenges' where he provides the basic outline of a game design and challenges people to implement and iterate on the design to hopefully create a fun game. A couple of these challenges come with freely provided graphics, although in this case the assets are intended for use if undertaking the challenge (a fantastic learning exercise!) in question rather than for general use: Prototyping Challenge: Play With Your Peas Prototyping Challenge: Fishing Girl Glitch - Public Domain Art (and code) All assets from a defunct web-based MMO game, made freely available under CC0 1.0 Universal licensing terms. Get it HERE. Most of the graphics are available in .fla and .swf formats. Quaternius Quaternius offers a large range of basic low-poly models with CC0 licensing. You can also support his efforts by purchasing all of his sets in a single file for $1. OpenGameArt.org OpenGameArt have a huge collection of different art, constantly added to by new and existing contributors. Quality and style vary, but there is some really good material available if you're willing to spend some time looking. Note that licensing terms vary, so be sure to check each item's license before use. Game-Icons.net At the time of writing, Game-Icons.net offers 3044 free icons in SVG and PNG formats with CC BY 3.0 licensing (which requires attribution). The built in editor on the site will allow you to alter the icon size and apply some simple properties (such as background type and colour). AI War 2.0 graphics library Graphics from the space RTS game AI War: Fleet Command. Free for use by indie developers. Get it HERE. Reiner's Tilesets 2d and 3d graphics (use the menu at the top of the site to view categories) available under these licensing terms. MakeHuman MakeHuman is an open source (AGPL licenced) tool for creating 3d characters. Output characters can be used under a permissive CC0 license under certain conditions. GameDev.Market There are some free assets available via the GameDev Marketplace (our very own asset store!). Looking to hire an artist for custom work? Check out our Contractors section, or advertise your project in our Game Jobs board (for paid commercial projects) or Hobby Classifieds forum (for free hobbyist projects). Looking to purchase pre-made assets? Try the GameDev Marketplace, or other asset stores such as GameDev Market (not affiliated with us!), the Unity Asset Store, the Unreal Marketplace, or others.
  3. Rutin

    Stone Gargoyle Head

    From the album: My Graphics Bin

    This is a stone gargoyle head I did awhile back. Part of my blog post: https://www.gamedev.net/blogs/entry/2265296-gargoyle-art-head-piece/
  4. In this video we will learn to control the 3d interface of blender
  5. A Unity Asset for customizable lowpoly weapons and shields. - Full Version: http://u3d.as/1hvG - Free Version: http://u3d.as/1jZV You can get the character model used in the video here (for FREE!): http://u3d.as/1kP7
  6. A Unity Asset for customizable lowpoly weapons and shields. - Full Version: http://u3d.as/1hvG - Free Version: http://u3d.as/1jZV You can get the character model used in the video here (for FREE!): http://u3d.as/1kP7 View full story
  7. [UNITY ASSET] Customizable lowpoly weapons and shields. - Full Version: http://u3d.as/1hvG - Free Version: http://u3d.as/1jZV You can get the character model used in the video here (for FREE!): http://u3d.as/1kP7
  8. Nilmani Gautam

    Blender : Intro to layout

    In this video we will learn to change the blender layout
  9. Last week wasn't concretely visual or anything... It was mainly an integration one. There was also some graphical updates plus I've also made part of the options menu. Graphics First, let's talk about those graphics. Previously, the skybox was of a solid colour. This was a placeholder skybox. However, I thought about it and came to the conclusion that it was about time to have a better one. I've searched on the internet and found this lovely gradient skybox, so I've added it to the game but with a bit of pizzazz. Basically, I've added a screen-positioned grid pattern and make a big dot in it representing the sun. I've loved it so much that I've decided to add it to my levels too! Here's how it looked previously: And here's how it looks now: I personally like how this looks. Also, previously the directional light that lights the scenes weren't following the colour palette, so I've added a bit of script to help with that, hence the different lighting... Integrations I've mainly had to link up the menus and the actual first level of the game. To do this I've used the Scene loading functions of Unity. I've added a nice loading screen with a working loading bar that fills up to the loading process' actual progression. There is, however, a bit of a hiccup while loading the level. The game window actually freezes and seems like it stopped working... This might be related to the loading process of the Music Player I've previously made: while the process loads in a different thread, the first load is done on the main process. This makes the game hang up until the first song actually loading... This is something I'm currently working on. Options Secondly, I've also added a bunch of drivers to the options screen. Let's take a look at each tab... General This is where general options will be. Right now, there's only a dropdown to switch languages, but eventually, there might be more options if it's needed. Graphics This is where the meat is. Here, the player can set many types of graphical settings, like resolution and quality settings. There are six quality presets: Very Low, Low, Medium, High, Very High and AESTHETIC (Ultra). There's also a seventh one, called Custom, where the player can set each graphical settings separately. As of now, this setting doesn't do anything, as it is only a driver. Audio This is where the player can set all its audio configs. Mainly this is where the player can adjust any volume sliders. There's also another section called "Others" where other audio settings can be set. As of right now, there's only a toggle indicating whenever or not the VaporMaker is active. There might be more options in the future. That's about it for options: the other tabs are still in development. Minor Updates Reflection Probes! Now there's a bunch of reflection probes in special rooms. This means that lights will feel more natural and specular materials will look better. Shader optimizations. I've optimized some shaders and the game builds quicker. (Speaking of build...) I've created a really dirty private build of the game. While still building, there was a lot of bugs and isn't really presentable. The important thing is that it builds properly and without any hiccups. I've fixed some bugs with state loading and overall scene progression. Previously the level scene was completely separate from the menu screen, meaning that a lot of states appeared twice between the scenes. Because these are supposed to be singletons, many of the level's controller were removed, breaking everything. Next week Next week is going to be the continuation of the integration. I mainly need to fix my loading screen hiccup problems and many other things. Afterwards, I might need to make an actual progression between each level. As of right now, there's only one level with no exits. Afterwards, it's gonna be boss time! And then after it's the usual suspects... I gotta say, with all that integration, I'll be soon ready to actually publish some kind of demo or test build by the end of December.
  10. Hello! I would like to introduce Diligent Engine, a project that I've been recently working on. Diligent Engine is a light-weight cross-platform abstraction layer between the application and the platform-specific graphics API. Its main goal is to take advantages of the next-generation APIs such as Direct3D12 and Vulkan, but at the same time provide support for older platforms via Direct3D11, OpenGL and OpenGLES. Diligent Engine exposes common front-end for all supported platforms and provides interoperability with underlying native API. Shader source code converter allows shaders authored in HLSL to be translated to GLSL and used on all platforms. Diligent Engine supports integration with Unity and is designed to be used as a graphics subsystem in a standalone game engine, Unity native plugin or any other 3D application. It is distributed under Apache 2.0 license and is free to use. Full source code is available for download on GitHub. Features: True cross-platform Exact same client code for all supported platforms and rendering backends No #if defined(_WIN32) ... #elif defined(LINUX) ... #elif defined(ANDROID) ... No #if defined(D3D11) ... #elif defined(D3D12) ... #elif defined(OPENGL) ... Exact same HLSL shaders run on all platforms and all backends Modular design Components are clearly separated logically and physically and can be used as needed Only take what you need for your project (do not want to keep samples and tutorials in your codebase? Simply remove Samples submodule. Only need core functionality? Use only Core submodule) No 15000 lines-of-code files Clear object-based interface No global states Key graphics features: Automatic shader resource binding designed to leverage the next-generation rendering APIs Multithreaded command buffer generation 50,000 draw calls at 300 fps with D3D12 backend Descriptor, memory and resource state management Modern c++ features to make code fast and reliable The following platforms and low-level APIs are currently supported: Windows Desktop: Direct3D11, Direct3D12, OpenGL Universal Windows: Direct3D11, Direct3D12 Linux: OpenGL Android: OpenGLES MacOS: OpenGL iOS: OpenGLES API Basics Initialization The engine can perform initialization of the API or attach to already existing D3D11/D3D12 device or OpenGL/GLES context. For instance, the following code shows how the engine can be initialized in D3D12 mode: #include "RenderDeviceFactoryD3D12.h" using namespace Diligent; // ... GetEngineFactoryD3D12Type GetEngineFactoryD3D12 = nullptr; // Load the dll and import GetEngineFactoryD3D12() function LoadGraphicsEngineD3D12(GetEngineFactoryD3D12); auto *pFactoryD3D11 = GetEngineFactoryD3D12(); EngineD3D12Attribs EngD3D12Attribs; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[0] = 1024; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[1] = 32; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[2] = 16; EngD3D12Attribs.CPUDescriptorHeapAllocationSize[3] = 16; EngD3D12Attribs.NumCommandsToFlushCmdList = 64; RefCntAutoPtr<IRenderDevice> pRenderDevice; RefCntAutoPtr<IDeviceContext> pImmediateContext; SwapChainDesc SwapChainDesc; RefCntAutoPtr<ISwapChain> pSwapChain; pFactoryD3D11->CreateDeviceAndContextsD3D12( EngD3D12Attribs, &pRenderDevice, &pImmediateContext, 0 ); pFactoryD3D11->CreateSwapChainD3D12( pRenderDevice, pImmediateContext, SwapChainDesc, hWnd, &pSwapChain ); Creating Resources Device resources are created by the render device. The two main resource types are buffers, which represent linear memory, and textures, which use memory layouts optimized for fast filtering. To create a buffer, you need to populate BufferDesc structure and call IRenderDevice::CreateBuffer(). The following code creates a uniform (constant) buffer: BufferDesc BuffDesc; BufferDesc.Name = "Uniform buffer"; BuffDesc.BindFlags = BIND_UNIFORM_BUFFER; BuffDesc.Usage = USAGE_DYNAMIC; BuffDesc.uiSizeInBytes = sizeof(ShaderConstants); BuffDesc.CPUAccessFlags = CPU_ACCESS_WRITE; m_pDevice->CreateBuffer( BuffDesc, BufferData(), &m_pConstantBuffer ); Similar, to create a texture, populate TextureDesc structure and call IRenderDevice::CreateTexture() as in the following example: TextureDesc TexDesc; TexDesc.Name = "My texture 2D"; TexDesc.Type = TEXTURE_TYPE_2D; TexDesc.Width = 1024; TexDesc.Height = 1024; TexDesc.Format = TEX_FORMAT_RGBA8_UNORM; TexDesc.Usage = USAGE_DEFAULT; TexDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS; TexDesc.Name = "Sample 2D Texture"; m_pRenderDevice->CreateTexture( TexDesc, TextureData(), &m_pTestTex ); Initializing Pipeline State Diligent Engine follows Direct3D12 style to configure the graphics/compute pipeline. One big Pipelines State Object (PSO) encompasses all required states (all shader stages, input layout description, depth stencil, rasterizer and blend state descriptions etc.) Creating Shaders To create a shader, populate ShaderCreationAttribs structure. An important member is ShaderCreationAttribs::SourceLanguage. The following are valid values for this member: SHADER_SOURCE_LANGUAGE_DEFAULT - The shader source format matches the underlying graphics API: HLSL for D3D11 or D3D12 mode, and GLSL for OpenGL and OpenGLES modes. SHADER_SOURCE_LANGUAGE_HLSL - The shader source is in HLSL. For OpenGL and OpenGLES modes, the source code will be converted to GLSL. See shader converter for details. SHADER_SOURCE_LANGUAGE_GLSL - The shader source is in GLSL. There is currently no GLSL to HLSL converter. To allow grouping of resources based on the frequency of expected change, Diligent Engine introduces classification of shader variables: Static variables (SHADER_VARIABLE_TYPE_STATIC) are variables that are expected to be set only once. They may not be changed once a resource is bound to the variable. Such variables are intended to hold global constants such as camera attributes or global light attributes constant buffers. Mutable variables (SHADER_VARIABLE_TYPE_MUTABLE) define resources that are expected to change on a per-material frequency. Examples may include diffuse textures, normal maps etc. Dynamic variables (SHADER_VARIABLE_TYPE_DYNAMIC) are expected to change frequently and randomly. This post describes the resource binding model in Diligent Engine. The following is an example of shader initialization: ShaderCreationAttribs Attrs; Attrs.Desc.Name = "MyPixelShader"; Attrs.FilePath = "MyShaderFile.fx"; Attrs.SearchDirectories = "shaders;shaders\\inc;"; Attrs.EntryPoint = "MyPixelShader"; Attrs.Desc.ShaderType = SHADER_TYPE_PIXEL; Attrs.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL; BasicShaderSourceStreamFactory BasicSSSFactory(Attrs.SearchDirectories); Attrs.pShaderSourceStreamFactory = &BasicSSSFactory; ShaderVariableDesc ShaderVars[] = { {"g_StaticTexture", SHADER_VARIABLE_TYPE_STATIC}, {"g_MutableTexture", SHADER_VARIABLE_TYPE_MUTABLE}, {"g_DynamicTexture", SHADER_VARIABLE_TYPE_DYNAMIC} }; Attrs.Desc.VariableDesc = ShaderVars; Attrs.Desc.NumVariables = _countof(ShaderVars); Attrs.Desc.DefaultVariableType = SHADER_VARIABLE_TYPE_STATIC; StaticSamplerDesc StaticSampler; StaticSampler.Desc.MinFilter = FILTER_TYPE_LINEAR; StaticSampler.Desc.MagFilter = FILTER_TYPE_LINEAR; StaticSampler.Desc.MipFilter = FILTER_TYPE_LINEAR; StaticSampler.TextureName = "g_MutableTexture"; Attrs.Desc.NumStaticSamplers = 1; Attrs.Desc.StaticSamplers = &StaticSampler; ShaderMacroHelper Macros; Macros.AddShaderMacro("USE_SHADOWS", 1); Macros.AddShaderMacro("NUM_SHADOW_SAMPLES", 4); Macros.Finalize(); Attrs.Macros = Macros; RefCntAutoPtr<IShader> pShader; m_pDevice->CreateShader( Attrs, &pShader ); Creating the Pipeline State Object To create a pipeline state object, define instance of PipelineStateDesc structure. The structure defines the pipeline specifics such as if the pipeline is a compute pipeline, number and format of render targets as well as depth-stencil format: // This is a graphics pipeline PSODesc.IsComputePipeline = false; PSODesc.GraphicsPipeline.NumRenderTargets = 1; PSODesc.GraphicsPipeline.RTVFormats[0] = TEX_FORMAT_RGBA8_UNORM_SRGB; PSODesc.GraphicsPipeline.DSVFormat = TEX_FORMAT_D32_FLOAT; The structure also defines depth-stencil, rasterizer, blend state, input layout and other parameters. For instance, rasterizer state can be defined as in the code snippet below: // Init rasterizer state RasterizerStateDesc &RasterizerDesc = PSODesc.GraphicsPipeline.RasterizerDesc; RasterizerDesc.FillMode = FILL_MODE_SOLID; RasterizerDesc.CullMode = CULL_MODE_NONE; RasterizerDesc.FrontCounterClockwise = True; RasterizerDesc.ScissorEnable = True; //RSDesc.MultisampleEnable = false; // do not allow msaa (fonts would be degraded) RasterizerDesc.AntialiasedLineEnable = False; When all fields are populated, call IRenderDevice::CreatePipelineState() to create the PSO: m_pDev->CreatePipelineState(PSODesc, &m_pPSO); Binding Shader Resources Shader resource binding in Diligent Engine is based on grouping variables in 3 different groups (static, mutable and dynamic). Static variables are variables that are expected to be set only once. They may not be changed once a resource is bound to the variable. Such variables are intended to hold global constants such as camera attributes or global light attributes constant buffers. They are bound directly to the shader object: PixelShader->GetShaderVariable( "g_tex2DShadowMap" )->Set( pShadowMapSRV ); Mutable and dynamic variables are bound via a new object called Shader Resource Binding (SRB), which is created by the pipeline state: m_pPSO->CreateShaderResourceBinding(&m_pSRB); Dynamic and mutable resources are then bound through SRB object: m_pSRB->GetVariable(SHADER_TYPE_VERTEX, "tex2DDiffuse")->Set(pDiffuseTexSRV); m_pSRB->GetVariable(SHADER_TYPE_VERTEX, "cbRandomAttribs")->Set(pRandomAttrsCB); The difference between mutable and dynamic resources is that mutable ones can only be set once for every instance of a shader resource binding. Dynamic resources can be set multiple times. It is important to properly set the variable type as this may affect performance. Static variables are generally most efficient, followed by mutable. Dynamic variables are most expensive from performance point of view. This post explains shader resource binding in more details. Setting the Pipeline State and Invoking Draw Command Before any draw command can be invoked, all required vertex and index buffers as well as the pipeline state should be bound to the device context: // Clear render target const float zero[4] = {0, 0, 0, 0}; m_pContext->ClearRenderTarget(nullptr, zero); // Set vertex and index buffers IBuffer *buffer[] = {m_pVertexBuffer}; Uint32 offsets[] = {0}; Uint32 strides[] = {sizeof(MyVertex)}; m_pContext->SetVertexBuffers(0, 1, buffer, strides, offsets, SET_VERTEX_BUFFERS_FLAG_RESET); m_pContext->SetIndexBuffer(m_pIndexBuffer, 0); m_pContext->SetPipelineState(m_pPSO); Also, all shader resources must be committed to the device context: m_pContext->CommitShaderResources(m_pSRB, COMMIT_SHADER_RESOURCES_FLAG_TRANSITION_RESOURCES); When all required states and resources are bound, IDeviceContext::Draw() can be used to execute draw command or IDeviceContext::DispatchCompute() can be used to execute compute command. Note that for a draw command, graphics pipeline must be bound, and for dispatch command, compute pipeline must be bound. Draw() takes DrawAttribs structure as an argument. The structure members define all attributes required to perform the command (primitive topology, number of vertices or indices, if draw call is indexed or not, if draw call is instanced or not, if draw call is indirect or not, etc.). For example: DrawAttribs attrs; attrs.IsIndexed = true; attrs.IndexType = VT_UINT16; attrs.NumIndices = 36; attrs.Topology = PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; pContext->Draw(attrs); Tutorials and Samples The GitHub repository contains a number of tutorials and sample applications that demonstrate the API usage. Tutorial 01 - Hello Triangle This tutorial shows how to render a simple triangle using Diligent Engine API. Tutorial 02 - Cube This tutorial demonstrates how to render an actual 3D object, a cube. It shows how to load shaders from files, create and use vertex, index and uniform buffers. Tutorial 03 - Texturing This tutorial demonstrates how to apply a texture to a 3D object. It shows how to load a texture from file, create shader resource binding object and how to sample a texture in the shader. Tutorial 04 - Instancing This tutorial demonstrates how to use instancing to render multiple copies of one object using unique transformation matrix for every copy. Tutorial 05 - Texture Array This tutorial demonstrates how to combine instancing with texture arrays to use unique texture for every instance. Tutorial 06 - Multithreading This tutorial shows how to generate command lists in parallel from multiple threads. Tutorial 07 - Geometry Shader This tutorial shows how to use geometry shader to render smooth wireframe. Tutorial 08 - Tessellation This tutorial shows how to use hardware tessellation to implement simple adaptive terrain rendering algorithm. Tutorial_09 - Quads This tutorial shows how to render multiple 2D quads, frequently swithcing textures and blend modes. AntTweakBar sample demonstrates how to use AntTweakBar library to create simple user interface. Atmospheric scattering sample is a more advanced example. It demonstrates how Diligent Engine can be used to implement various rendering tasks: loading textures from files, using complex shaders, rendering to textures, using compute shaders and unordered access views, etc. The repository includes Asteroids performance benchmark based on this demo developed by Intel. It renders 50,000 unique textured asteroids and lets compare performance of D3D11 and D3D12 implementations. Every asteroid is a combination of one of 1000 unique meshes and one of 10 unique textures. Integration with Unity Diligent Engine supports integration with Unity through Unity low-level native plugin interface. The engine relies on Native API Interoperability to attach to the graphics API initialized by Unity. After Diligent Engine device and context are created, they can be used us usual to create resources and issue rendering commands. GhostCubePlugin shows an example how Diligent Engine can be used to render a ghost cube only visible as a reflection in a mirror.
  11. Vivid3DDev

    3D FusionIDE W.I.P 1 -

    Here is the welcome screen to fusionIDE - it is a multi-state, multi-form custom editor wrote 100% using vivid3d's 3d and 2d capabilities. The UI is called ResonanceUI. This is all OpenGL based. Here is the video of the welcome screen.
  12. After spending many hours painstakingly attempting to model creatures entirely by hand, I finally discovered (a couple of years ago) the skin modifier in Blender, which is a fantastic quick way to build organic creatures and shapes, especially for the artistically challenged like myself, and also makes rigging a breeze. I thought I would write a quick description for those unfamiliar. If you want ultimate control, particularly for a low poly creature, there is no substitute for manually creating polys. However, this can be very time consuming and tedious. If you are instead in a position where you are willing to trade off speed of creation against 'perfect rendering efficiency', or are making medium/high poly models, or models for later sculpting, then one of the options available is the skin modifier. Using the skin modifier, instead of modelling the skin by hand you place the joints (as vertices) of a creature to build a kind of skeleton, and allow the skin modifier to automagically generate a skin around this skeleton. Process Typically I start off by creating a plane, then go into edit mode, and merge the vertices to 1 in the centre. Next set up the modifier stack to create the skin. At the top of the stack goes a mirror modifier, because most animals are symmetrical bilaterally. Next goes the skin modifier, which creates a simple box-like skin around the skeleton. Finally add a subsurface modifier to smooth the skin, and make it more organic. Once the modifier stack is ready you can begin modelling. In the case of this bird, I started with a top-down view. Select the start vertex (there should now be a 'blob' around the single merged vertex), and create the skeleton by pressing 'e' to extrude and place a new vertex. I did this to place several vertices to create a backbone for the bird. You can then create wings and legs by picking one of the vertices in the backbone and extruding to the side. If you follow this process you can form a rough top-down skeleton, it doesn't have to be exact because it is easy to adjust, that is one of the beauties of skin modifier. I find it useful to google pictures of the skeleton of the animal for reference. Next look at side views and adjust the up-down position of the vertices (joints). The legs needed to be going downwards, and the head slightly up. Once I am happy with the basics of the structure, I start to fill it out. You do this by selecting a vertex, then pressing 'ctrl-a' then dragging with the mouse. You can make the skin thicker or thinner at each vertex. This can quickly give you a reasonable shape. You can further refine the shape by pressing 'ctrl-a' then limiting to either the x or y axis by pressing 'x' or 'y' before dragging. I used this to give a broad flat tail and wings. Conclusion Pretty soon you can build a pretty good model. You can tweak a few things in the skin modifier, especially set a root vertex (e.g. pelvis) can make it easier for later animation. Skin modifier also makes rigging easy. Once you are happy with your skeleton, make a copy of the whole thing (so you don't lose the original), then choose 'create armature' from the skin modifier. This will create an armature and link it to the mesh so it is ready for posing and animating! I also typically choose smooth shading in the skin modifier, then manually add hard edges in mesh edit mode (ctrl-e, hard edge, and use in combination with the edge-split modifier). I also use this to select seams for uv mapping. Note that once I finish the skin modifier version I usually have to do a little tweaking of the polys manually, because there are some things it is not good at. Anyway, this has been a brief introduction to this method, I would encourage trying it and following some youtube tutorials. After some decimating and very rough texturing (~640 tris)
  13. Hello, I'm trying to make a PBR vulkan renderer and I wanted to implement Spherical harmonics for the irradiance part (and maybe PRT in the future but that's another story). the evaluation on the shader side seems okay (it look good if I hardcode the SH directly in the shader) but when I try to generate it from a .hdr map it output only gray scale. It's been 3 days I'm trying to debug now I just have no clue why all my colour coefficients are gray. Here is the generation code: SH2 ProjectOntoSH9(const glm::vec3& dir) { SH2 sh; // Band 0 sh.coef0.x = 0.282095f; // Band 1 sh.coef1.x = 0.488603f * dir.y; sh.coef2.x = 0.488603f * dir.z; sh.coef3.x = 0.488603f * dir.x; // Band 2 sh.coef4.x = 1.092548f * dir.x * dir.y; sh.coef5.x = 1.092548f * dir.y * dir.z; sh.coef6.x = 0.315392f * (3.0f * dir.z * dir.z - 1.0f); sh.coef7.x = 1.092548f * dir.x * dir.z; sh.coef8.x = 0.546274f * (dir.x * dir.x - dir.y * dir.y); return sh; } SH2 ProjectOntoSH9Color(const glm::vec3& dir, const glm::vec3& color) { SH2 sh = ProjectOntoSH9(dir); SH2 shColor; shColor.coef0 = color * sh.coef0.x; shColor.coef1 = color * sh.coef1.x; shColor.coef2 = color * sh.coef2.x; shColor.coef3 = color * sh.coef3.x; shColor.coef4 = color * sh.coef4.x; shColor.coef5 = color * sh.coef5.x; shColor.coef6 = color * sh.coef6.x; shColor.coef7 = color * sh.coef7.x; shColor.coef8 = color * sh.coef8.x; return shColor; } void SHprojectHDRImage(const float* pixels, glm::ivec3 size, SH2& out) { double pixel_area = (2.0f * M_PI / size.x) * (M_PI / size.y); glm::vec3 color; float weightSum = 0.0f; for (unsigned int t = 0; t < size.y; t++) { float theta = M_PI * (t + 0.5f) / size.y; float weight = pixel_area * sin(theta); for (unsigned int p = 0; p < size.x; p++) { float phi = 2.0 * M_PI * (p + 0.5) / size.x; color = glm::make_vec3(&pixels[t * size.x + p]); glm::vec3 dir(sin(phi) * cos(theta), sin(phi) * sin(theta), cos(theta)); out += ProjectOntoSH9Color(dir, color) * weight; weightSum += weight; } } out.print(); out *= (4.0f * M_PI) / weightSum; } outside of the SHProjectHDRImage function that's pretty much the code from MJP that you can check here: https://github.com/TheRealMJP/LowResRendering/blob/2f5742f04ab869fef5783a7c6837c38aefe008c3/SampleFramework11/v1.01/Graphics/SH.cpp I'm not doing anything fancy in term of math or code but I that's my first time with those so I feel like I forgot something important. basically for every pixel on my equi-rectangular hdr map I generate a direction, get the colour and project it on the SH but strangely I endup with a SH looking like this: coef0: 1.42326 1.42326 1.42326 coef1: -0.0727784 -0.0727848 -0.0727895 coef2: -0.154357 -0.154357 -0.154356 coef3: 0.0538229 0.0537928 0.0537615 coef4: -0.0914876 -0.0914385 -0.0913899 coef5: 0.0482638 0.0482385 0.0482151 coef6: 0.0531449 0.0531443 0.0531443 coef7: -0.134459 -0.134402 -0.134345 coef8: -0.413949 -0.413989 -0.414021 with the HDR map "Ditch River" from this web page http://www.hdrlabs.com/sibl/archive.html but I also get grayscale on the 6 other hdr maps I tried from hdr heaven, it's just different gray. If anyone have any clue that would be really welcome.
  14. Hello! I tried to implement the Morgan's McGuire method, but my attempts failed. He described his method here: Screen Space Ray Tracing. Below is my code and screenshot. SSLR fragment shader: #version 330 core uniform sampler2D normalMap; // in view space uniform sampler2D depthMap; // in view space uniform sampler2D colorMap; uniform sampler2D reflectionStrengthMap; uniform mat4 projection; uniform mat4 inv_projection; in vec2 texCoord; layout (location = 0) out vec4 fragColor; vec3 calcViewPosition(in vec2 texCoord) { // Combine UV & depth into XY & Z (NDC) vec3 rawPosition = vec3(texCoord, texture(depthMap, texCoord).r); // Convert from (0, 1) range to (-1, 1) vec4 ScreenSpacePosition = vec4(rawPosition * 2 - 1, 1); // Undo Perspective transformation to bring into view space vec4 ViewPosition = inv_projection * ScreenSpacePosition; ViewPosition.y *= -1; // Perform perspective divide and return return ViewPosition.xyz / ViewPosition.w; } // By Morgan McGuire and Michael Mara at Williams College 2014 // Released as open source under the BSD 2-Clause License // http://opensource.org/licenses/BSD-2-Clause #define point2 vec2 #define point3 vec3 float distanceSquared(vec2 a, vec2 b) { a -= b; return dot(a, a); } // Returns true if the ray hit something bool traceScreenSpaceRay( // Camera-space ray origin, which must be within the view volume point3 csOrig, // Unit length camera-space ray direction vec3 csDir, // A projection matrix that maps to pixel coordinates (not [-1, +1] // normalized device coordinates) mat4x4 proj, // The camera-space Z buffer (all negative values) sampler2D csZBuffer, // Dimensions of csZBuffer vec2 csZBufferSize, // Camera space thickness to ascribe to each pixel in the depth buffer float zThickness, // (Negative number) float nearPlaneZ, // Step in horizontal or vertical pixels between samples. This is a float // because integer math is slow on GPUs, but should be set to an integer >= 1 float stride, // Number between 0 and 1 for how far to bump the ray in stride units // to conceal banding artifacts float jitter, // Maximum number of iterations. Higher gives better images but may be slow const float maxSteps, // Maximum camera-space distance to trace before returning a miss float maxDistance, // Pixel coordinates of the first intersection with the scene out point2 hitPixel, // Camera space location of the ray hit out point3 hitPoint) { // Clip to the near plane float rayLength = ((csOrig.z + csDir.z * maxDistance) > nearPlaneZ) ? (nearPlaneZ - csOrig.z) / csDir.z : maxDistance; point3 csEndPoint = csOrig + csDir * rayLength; // Project into homogeneous clip space vec4 H0 = proj * vec4(csOrig, 1.0); vec4 H1 = proj * vec4(csEndPoint, 1.0); float k0 = 1.0 / H0.w, k1 = 1.0 / H1.w; // The interpolated homogeneous version of the camera-space points point3 Q0 = csOrig * k0, Q1 = csEndPoint * k1; // Screen-space endpoints point2 P0 = H0.xy * k0, P1 = H1.xy * k1; // If the line is degenerate, make it cover at least one pixel // to avoid handling zero-pixel extent as a special case later P1 += vec2((distanceSquared(P0, P1) < 0.0001) ? 0.01 : 0.0); vec2 delta = P1 - P0; // Permute so that the primary iteration is in x to collapse // all quadrant-specific DDA cases later bool permute = false; if (abs(delta.x) < abs(delta.y)) { // This is a more-vertical line permute = true; delta = delta.yx; P0 = P0.yx; P1 = P1.yx; } float stepDir = sign(delta.x); float invdx = stepDir / delta.x; // Track the derivatives of Q and k vec3 dQ = (Q1 - Q0) * invdx; float dk = (k1 - k0) * invdx; vec2 dP = vec2(stepDir, delta.y * invdx); // Scale derivatives by the desired pixel stride and then // offset the starting values by the jitter fraction dP *= stride; dQ *= stride; dk *= stride; P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter; // Slide P from P0 to P1, (now-homogeneous) Q from Q0 to Q1, k from k0 to k1 point3 Q = Q0; // Adjust end condition for iteration direction float end = P1.x * stepDir; float k = k0, stepCount = 0.0, prevZMaxEstimate = csOrig.z; float rayZMin = prevZMaxEstimate, rayZMax = prevZMaxEstimate; float sceneZMax = rayZMax + 100; for (point2 P = P0; ((P.x * stepDir) <= end) && (stepCount < maxSteps) && ((rayZMax < sceneZMax - zThickness) || (rayZMin > sceneZMax)) && (sceneZMax != 0); P += dP, Q.z += dQ.z, k += dk, ++stepCount) { rayZMin = prevZMaxEstimate; rayZMax = (dQ.z * 0.5 + Q.z) / (dk * 0.5 + k); prevZMaxEstimate = rayZMax; if (rayZMin > rayZMax) { float t = rayZMin; rayZMin = rayZMax; rayZMax = t; } hitPixel = permute ? P.yx : P; // You may need hitPixel.y = csZBufferSize.y - hitPixel.y; here if your vertical axis // is different than ours in screen space sceneZMax = texelFetch(csZBuffer, ivec2(hitPixel), 0).r; } // Advance Q based on the number of steps Q.xy += dQ.xy * stepCount; hitPoint = Q * (1.0 / k); return (rayZMax >= sceneZMax - zThickness) && (rayZMin < sceneZMax); } void main() { vec3 normal = texture(normalMap, texCoord).xyz * 2.0 - 1.0; vec3 viewPos = calcViewPosition(texCoord); // Reflection vector vec3 reflected = normalize(reflect(normalize(viewPos), normalize(normal))); vec2 hitPixel; vec3 hitPoint; bool tssr = traceScreenSpaceRay( viewPos, reflected, projection, depthMap, vec2(1366, 768), 0.0, // zThickness -1.0, // nearPlaneZ 1.0, // stride 0.0, // jitter 32, // maxSteps 32, // maxDistance hitPixel, hitPoint ); //fragColor = texture(colorMap, hitPixel); if (tssr) fragColor = mix(texture(colorMap, texCoord), texture(colorMap, hitPixel), texture(reflectionStrengthMap, texCoord).r); else fragColor = texture(colorMap, texCoord); } Screenshot: I create a projection matrix like this: glm::perspective(glm::radians(90.0f), (float) WIN_W / (float) WIN_H, 1.0f, 32.0f) This is what will happen if I display the image like this fragColor = texture(colorMap, hitPixel) colorMap: normalMap: depthMap: What am I doing wrong? Perhaps I misunderstand the value of csOrig, csDir and zThickness, so I would be glad if you could help me understand what these variables are.
  15. 3dBookman

    The 3D book

    After a break of several years the 3D book project is back on. A few short words now on what this blog is about. I have to deliver my wife to the bus station in a few minutes, then a week alone so may have the time then to explain things. But the 3D book is something I started in 014 and put several years into, then the break, now on again. A win32 app with a text window and an ogl window. I just remembered I had something written on this so here it is I write to see if anyone in this community of game developers, programmers, enthusiasts, may be interested in a project I have been developing[off and on] for several years now. So follows a short description of this project, which I call the 3D-Book project. The 3D-Format Reader: A new format of media. Imagine opening a book, the left page is conventional formatted text - on the right page a 3D animation of the subject of the text on the left hand page. The text page with user input from mouse and keyboard, the 3D page with user intput from a game pad. An anatomy text for a future surgeon, with the a beating heart in 3D animation. A childrens story adventure book with a 3D fantasy world to enter on the right page. ... Currently 3D-Format Reader consists of a C++ Windows program: Two "child" windows in a main window frame. Two windows: a text-2D rendering window and a 3D-rendering window. The text-2D window, as its' name implies, displays text and 2D graphics; it is programmed using Microsoft's DirectWrite text formatting API and Microsoft's Direct2D API for 2D graphics. The 3D-rendering window uses the OpenGL API. A 3DE-Book page is formatted in one of two possible modes: DW_MODE or GL_MODE. In GL_MODE both windows are shown; the text-2D rendering window is on the left and the 3D OpenGL window is on the right. In DW_MODE, only the text-2D rendering window is shown, the OpenGL window is hidden (Logically it is still there, it has just been given zero width). The 3D-Format Reader reads text files, which consists of the text of the book, control character for the formatting of text, (bold, underline, ...), display of tables, loading of images(.jpg .png ...), and control of 2D and 3D routines. 3D-Reader programming is based on a Model-View-Controller (MVC) architecture. The MVC design is modular: The Controller component handles user input from the operating system , the Model component processes the input, and the View component sends output back to the user on the display. Typical Parent-Child windows programs have multiple "call back" window procedures(winProcs): One for the parent window and one for child window. The MVC model, simplifies message routing by using a call-back window procedure which receives Windows messages for the main window, the text-2D window and the OGL window. A sample MVC program by Song Ho Ahn was used as a template for the 3DE-Reader. Rushed for time now, so a hasty sign off and thanks for reading. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 8 - 21 -18 I spent the last few days working on procedural mesh generation. First looking to find a bit of code to do what I had in mind. Which begs the question: What did I have in mind? I just wanted a cube mesh generator such that... Requirements Input: An integer n = units from origin to cube face. Output: The vertices for a unit cube centered on the origin. 8n² triangles per cube face. 3 times 8n² verts in clockwise winding order (from the outside of the cube) ready for the rendering pipeline. Screenshot of some cubes generated with the procedural cube mesh generator. That was about it for the output requirements. I did not want to hand code even a single vertex and did not want to load a mesh file. I was sure the code was out there somewhere, but was not finding it. So, a bit reluctantly at first, I started coding the mesh generator. I started enjoying creating this thing and stopped searching for the "out-there-somewhere" code; although still curious how others did this. Analysis First question: How do we number the verts? It would be great to conceive of some concise algorithm to put out the cube face verts all in clockwise order for the outside faces of the cube directly. That seemed beyond me so I plodded along step by step. I decided to just use a simple nested loop to generate the cube face verts and number them in the order they were produced. The hope(and the presumption) was: The loop code was in some order, running thru the x y and z coordinates in order, from -n to +n, therefore the output would be a recognizable pattern. The simple nested loop vert generator did not let us down: It gave us a recognizable pattern, at least for this face. It turned out (as expected now) that all six faces have similar recognizable patterns. Plotting the first row or two of verts you can easily see how to run the rest of the pattern. Plot of the first(of six) cube faces verts output by the vert generator: Input of n: There are (2n+1)² verts per cube face, or 25 verts for n = 2. This is looking at the x = -n face from the outside of the cube. To simplify the math it helps to define s = 2n. Then there are (s + 1)² verts, or 25 for s = 4 s² cells on the face, or 16 for 4 = 2. We are going divide each cell into 2 triangles, so there are 2s² triangles per face, or 32 for s = 4. Second question: What pattern for the triangles? How to number the 2s² = 32 triangles? What we want in the end is a bit of code such that... for triangles T[0] thru T[2s²-1] or T[0] thru T[31]( for n = 4), we have T[N] = f0(N), f1(N), f2(N). Where f0(N) gives the first vertex of T[N] as a function of N. and f1 and f2 give the second and third verts, all in CW winding order looking into the cube of course. Here the choice is a bit arbitrary, but it would seem to make things easier if we can manage to have the order of triangles follow the order of verts to a degree. Numbering the triangles. And now the problem becomes: Look at the triangle vert list, T0 - T8...T31 in the image, and try to discern some pattern leading us to the sought after functions f0(N), f1(N), f2(N) where N is the number of the triangle, 0 thru 2s²-1. This really is the holy grail of this whole effort; then we have T[N] = f0(N), f1(N), f2(N) and that list of verts can be sent directly to the rendering pipeline. Of course we want these functions to work for all six faces and all 12s² triangles to cover the cube. But first let's see if we can just do this one face, 0 thru 2s²-1.. Thru a bit of trial and error the 32 triangles(T0 - T31) were ordered as shown. Now we have an ordered list of the triangles and the verts from our loop. T0 = 0 5 6 T1 = 6 1 0 T2 = 1 6 7 T3 = 7 2 1 T4 = 2 7 8 T5 = 8 3 2 T6 = 3 8 9 T7 = 9 4 3 T8 = 5 10 11 ... T30 T31. If we can find a pattern in the verts on the right side of this list; we can implement it in an algorithm and the rest is just coding. Pattern recognition: It appears T2 = T0 with 1 added to each component T3 = T1 with 1 added to each component In general T[N+2] = T[N] with 1 added to each component, until we come to T8 at least. Also it is hard to recognize a relation between the even and odd triangles,To see what is happening here it helps to look at an image of the generalized case where n can take on any integer value n > 0. Looking for patterns in this generalized(for any n) vert plot we see... We have defined s = 2n. The 4 corner coordinates(+-n,+-n) of the x = - n cube face, one at each corner (+-n,+-n). There are (s+1)² verts/face numbered (0 thru (s+1)² -1). There are 2s² triangles/face numbered (0 thru 2s² -1). They are indicated in red. It's not as bad as it looks iff you break it down. Let's look at the even triangles only and just the 0th vert of these triangles. For any row we see the number of that first vert of the even triangles just increases by one going down the row. We can even try a relation such as T[N].0 = N/2. Here T[N].0 denotes the 0th vert of th Nth triangle. Which works until we have to jump to the next row. Every time we jump a row we T[N+1].0 = T[N].0 + 2 for the first triangle in the higher row. So we need a corrective term to the T[N].0 = N/2 relation that adds 1 every time we jump a row. We can use computer integer division to generate such a term and N/2s is such a term. It only changes value when we jump rows and we get our first function ... f0(N) = N/2 + N/2s. (even triangles) Remember the integer division will discard any remainder from the terms and check this works for the entire cube face, but only for the even triangles. What about the odd triangles? Going back to the triangle vs vert list for the specific case n = 2, s = 4 for the first row; we see for the odd triangles T[N].0 = T[N-1].0 + s + 2. And adding this term, s + 2 to the formula for the even triangle 0th vert we get f0[N] for the odd triangles. f0(N) = N/2 + N/2s + s + 2. (odd triangles) Continuing this somewhat tedious analysis for the remaining functions f1(N), f2(N) we eventually have these relations for the x = -n cube face triangles. for N = 0 thru N = 2s² - 1. defining m = N/2 + N/2s. T[N] = m, m + s + 1, m + s + 2 T[N] = f0(N), f1(N), f2(N). (even N) T[N] = m + s + 2, m + 1, m T[N] = f0'(N), f1'(N), f2'(N) (odd N) So it turns out we have two sets of functions for the verts, fn(N) for the even triangles and fn'(N) for the odd. To recap here; we now have formulae for all the T[N] verts as functions of N and the input parameter n: Input: An integer n = units from origin to cube face. But this is only for the first face x = -n, we have five more faces to determine. So the question is: Do these formulae work for the other faces? And the answer is no they do not, but going through a similar analysis for the remaining face gives similar T[N] = f0(N), f1(N), f2(N) for them. There is still the choice of how to number the remaining triangles and verts on the remaining five faces, and the f0(N), f1(N), f2(N) will depend on the somewhat arbitrary choice of how we do the numbering. For the particular choice of a numbering scheme I ended up making, it became clear how to determine the f0(N), f1(N), f2(N) for the remaining faces. It required making generalized vert plots for the remaining five face similar to the previous image. Then these relation emerged... For face x = -n T[N] N(0 thru 2²-1) we have the f0(N), f1(N), f2(N), even and odd For face x = n T[N] N(2s² thru 4s²-1) add (s+1)² to the x=-n face components and reverse the winding order For face y = -n T[N] N(4s² thru 6s²-1) add 2(s+1)² to the x=-n face components and reverse the winding order For face y = n T[N] N(6s² thru 8s²-1) add 3(s+1)² to the x=-n face components For face z = -n T[N] N(8s²0 thru 10s²-1) add 4(s+1)² to the x=-n face components For face z = n T[N] N(10s²0 thru 12s²-1) add 5(s+1)² to the x=-n face components and reverse the winding order And these are enough to allow us to write explicit expressions for all 12n² triangles for all 6 faces T[N] and what remains to be done is to implement these expression in code. Which turned out to be a much simpler task than finding the f0(N), f1(N), f2(N) and resulted in a surprisingly short bit of code. Implementation I have attempted to make this C++ snippet of code as generic as possible and have removed any dev-platform specific #includes and the like. GLM, a C++ mathematics library for graphics developed by Christophe Riccio is used. It is a header only library. https://github.com/g-truc/glm/releases/download/0.9.9.0/glm-0.9.9.0.zip That is the only outside dependency. // Procedural cube face verticies generator #include <vector> #include <glm/gtc/matrix_transform.hpp> struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle }; /* std::vector<Triangle> cube_Faces(int n) Input: integer 'n'; the units from origin to cube face. Output: vector<Triangle> glTriangle; container for the 12*(2*n)² triangles covering the 6 cube faces. */ std::vector<Triangle> cube_Faces(int n){ size_t number_of_triangles(12*(2*n )*(2*n)); size_t number_of_face_verts(6*(2*n +1 )*(2*n+1)); std::vector<glm::vec3> face_verts(number_of_face_verts); std::vector<Triangle> glTriangle(number_of_triangles); // Generate the 6*(2n +1 )² face verts ------------------------------- int l(0); for(int i = 0; i < 6; i++){ for(int j = -n; j <= n; j++){ for(int k = -n; k <= n; k++){ // Below "ifS" strip out all interior cube verts. if( i == 0){ // do yz faces face_verts[l].x = (float)(-n); //x face_verts[l].y = (float)j; //y face_verts[l].z = (float)k;}//z if( i == 1){ // do yz faces face_verts[l].x = (float)(n); //x face_verts[l].y = (float)j; //y face_verts[l].z = (float)k;}//z if( i == 2){ // do zx faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)(-n); //y face_verts[l].z = (float)k;}//z if( i == 3){ // do zx faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)(n); //y face_verts[l].z = (float)k;}//z if( i == 4){ // do xy faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)k; //y face_verts[l].z = (float)(-n);}//z if( i == 5){ // do xy faces face_verts[l].x = (float)j; //x face_verts[l].y = (float)k; //y face_verts[l].z = (float)(n);}//z l++; } } } // Generate the 12*(2*n)² triangles from the face verts ------- int s = 2*n; int q = 2*s*s; int a = (s+1)*(s+1); int f(0); int r(0); int h(0); for( int N=0; N < number_of_triangles; ){ // triangles already in CW winding if( N < q || N < 5*q && N > 3*q - 1 ){ // do the even indicies f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; glTriangle[N].vert[0] = face_verts[h]; glTriangle[N].vert[1] = face_verts[s + 1 + h]; glTriangle[N].vert[2] = face_verts[s + 2 + h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; // do the odd indicies glTriangle[N].vert[0] = face_verts[s + 2 + h]; glTriangle[N].vert[1] = face_verts[ 1 + h]; glTriangle[N].vert[2] = face_verts[h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; } // triangles needing reverse order for CW winding if( N > 5*q - 1 || N < 3*q && N > q - 1 ){ // do the even indicies glTriangle[N].vert[0] = face_verts[s + 2 + h]; glTriangle[N].vert[1] = face_verts[s + 1 + h]; glTriangle[N].vert[2] = face_verts[h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; // do the odd indicies glTriangle[N].vert[0] = face_verts[h]; glTriangle[N].vert[1] = face_verts[1 + h]; glTriangle[N].vert[2] = face_verts[s + 2 + h]; N++; f= q*(N/q); r = a*(N/q); h = (N-f)/2 + (N-f)/(2*s) + r; } } // Normalize the cube to side = 1 ------------------------------ for(int i = 0; i < number_of_triangles; i++){ glTriangle[i].vert[0].x = glTriangle[i].vert[0].x/(2.0*(float)n); glTriangle[i].vert[0].y = glTriangle[i].vert[0].y/(2.0*(float)n); glTriangle[i].vert[0].z = glTriangle[i].vert[0].z/(2.0*(float)n); glTriangle[i].vert[1].x = glTriangle[i].vert[1].x/(2.0*(float)n); glTriangle[i].vert[1].y = glTriangle[i].vert[1].y/(2.0*(float)n); glTriangle[i].vert[1].z = glTriangle[i].vert[1].z/(2.0*(float)n); glTriangle[i].vert[2].x = glTriangle[i].vert[2].x/(2.0*(float)n); glTriangle[i].vert[2].y = glTriangle[i].vert[2].y/(2.0*(float)n); glTriangle[i].vert[2].z = glTriangle[i].vert[2].z/(2.0*(float)n); }; return glTriangle; } The rendering was done using OpenGl. // OGL render call to the cube mesh generator - PSUEDOCODE int n(2); int cube_triangle_Count = (12*(2*n)*(2*n)); std::vector<Triangle> cube_Triangles(cube_triangle_Count); cube_Triangles = cube_Faces(n); glBindBuffer(GL_ARRAY_BUFFER, uiVBO[0]); glBufferData(GL_ARRAY_BUFFER, cube_Triangles.size()*sizeof(Triangle), &cube_Triangles[0], GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0); glEnableVertexAttribArray(0); glDrawArray(GL_TRIANGLES,0,3*cube_triangle_Count); This just gets the position attribute of the cube face triangle verts; for the color and other attributes there are a couple of options: Use separate GL_ARRAY_BUFFERS for the color and other attributes. Or add attributes to the Triangle struct... struct Triangle { glm::vec3 vert[3]; // the three verts of the triangle attribute1; attribute2; ... }; Screenshot of the spherified cube. What's next? Now that we have the cube mesh what we can do with with it practically unlimited. The first thing I did was turn it into a sphere. Playing with tesselating the cube or sphere or stellating it with different patterns; might do. Ended up trying a few matrix transformations on the cube mesh. These are shown in the image below. These shapes are result short bits of code like the code for the column shape below. //Column for(int i = 0; i < number_of_triangles; i++){ for(int j = 0; j < 3; j++){ if( glTriangle[i].vert[j].y < 0.5f && glTriangle[i].vert[j].y > -0.5f ){ float length_of_v = sqrt((glTriangle[i].vert[j].x * glTriangle[i].vert[j].x) + (glTriangle[i].vert[j].z * glTriangle[i].vert[j].z)); glTriangle[i].vert[j].x = 0.5f*glTriangle[i].vert[j].x/length_of_v; glTriangle[i].vert[j].z = 0.5f*glTriangle[i].vert[j].z/length_of_v; } } } Doing this; the blacksmith at his forge analogy soon presents. The mesh is the ingot, hammer matricies stretch, round and bend it against the fixed geometry of the anvil - coordinate system. I am the smith. Tetrahedron The tetrahedron is the platonic solid with the least number of faces(4), edges(6), and verts(4). In antiquity it was associated with the element of fire due to its' sharp vertices. The algorithm for the tetrahedron mesh was developed in a similar way to the cube, but here it seemed simpler to get a routine for just one face - an equilateral triangle - and use matrix translations and rotations to form the complete tetrahedron. So more like origami or tinsmithing than blacksmithing. Procedural tetrahedron screenshot. The n = 4 and the general case To get an routine for the general case, n an integer > 0, a bit of what I think is known as mathematical induction was used. PSUEDOCODE Spin = glm::rotate( PI/3, zaxis ); //matrix: rotate 60 degrees around z axis for(int row = 0; row < n; row++){ // go row by row count = 0; // set first triangle in the row = 0 for(int i = 2*n*row - row*row; i < 2*n*row - row*row + 2*n - 2*row - 1; i++){ // the magic happens here if (count % 2 == 0 ){ // triangle is even in the row -just translate x_Lat = glm::translate((count+row)/2n, row*height, 0.0f); for(int i = 0; i < 3; i++){ triangle[n].vert[i] = x_Lat*triangle[n].vert[i]; } } else{ // triangle is odd in the row - rotate then translate x_Lat = glm::translate(count+1+row)/2n, row*height, 0.0f); for(int i = 0; i < 3; i++){ triangle[n].vert[i] = x_Lat*Spin*triangle[n].vert[i]; } } count++; } } This is the psuedocode version of the routine which generates the verts for the n² triangles in a face. Getting this algorithm was a bit of a brain drain but looking for patterns in the image of the face allowed it to happen. We use a "seed" triangle, which is triangle 0 on the lower left of the figure. The verts of this one triangle are input; the rest of the n² triangles verts are generated by translating and rotating this seed triangle. Notice: There are n rows, every row has 2 less triangles than the row below. If we number the triangles from 0 to 2n - 2*row - 2, where the rows run 0 to n; the even triangles just need to be translated ... in the x direction by (count + row)/2n where count = their position in the row 0 to 2n - 2*row - 2. in the y direction by row*height. height = height of seed triangle. The odd triangles need to be rotated pi/3 = 60 degrees around the z axis then translated ... in the x direction by (count + row + 1)/2n where count = their position in the row 0 to 2n - 2*row - 2. in the y direction by row*height. height = height of seed triangle. Now we have a single face for the tetrahedron, to join the four faces together we need the angle between the faces called the dihedral angle. Dihedral Angle Each of the five platonic solids has a characteristic called the dihedral angle. This is the angle between the faces. For the cube it is 90 degrees or pi/2 radians. For the tetrahedron it is 70.528779° = arccos(1/3). The tetrahedron, with just four faces, is the simplest of the platonic solids. The simplest way I can think of to build it: Start with the four face stacked one on another, edges aligned. Imagine the top three faces each hinged to the bottom face along one edge. Then rotate each face around then hinged edge by arccos(1/3), the dihedral angle. That is the method of the bit of code shown below. PSUEDOCODE struct Triangle { glm::vec3 vert[3]; // the three verts of a triangle ... add other attributes, normals, colors }; /* std::vector<Triangle> tetrahedron(int n) Input: integer 'n'; the number of triangles along an edge of the tetrahedron. Output: vector<Triangle> ; container for the 4n² triangles covering the 4 tetrahedron faces. */ PSUEDOCODE vector<Triangle> tetrahedron(int n){ float tetra_Dihedral = acos(1/3); // --- Second face --- // We take the equilateral triangle face we generated above // which consisted of n² triangles. This face sits on the xy plane // with its lower left corner at the origin. // // Now we bend it -70.528779° = -arccos(1/3) around the // the X - axis. (Its' bottom edge) Spin = glm::rotate( -tetra_Dihedral, xaxis ); //just rotate for(int i = 0; i < n*n; i++){ for(int j = 0; j < 3; j++){ // This is the second face so triangle indecies // run from n² to 2n² tri_Angles[n*n + i].vert[j] = Spin*tri_Angles[i].vert[j] } } // The previous rotation gives CCW verts looking in from the // outside so need need to make them CW again for(int i = n*n; i < 2*n*n; i++){ swapVerts(tri_Angles[i].vert[0], tri_Angles[i].vert[2]); } // --- Third face --- // We take the original equilateral triangle face. // Now we bend it 70.528779° = arccos(1/3) around its left edge.. Spin = glm::rotate( tetra_Dihedral, glm::vec3(0.5f,0.866025f,0.0f)); for(int i = 0; i < N*N; n++){ for(int j = 0; j < 3; j++){ // This is the third face so triangle indecies // run from 2n² to 3n² tri_Angles[2*n*n + i].vert[j] = Spin*tri_Angles[i].vert[j] } } // The previous rotation gives CCW verts looking in from the // outside so need need to make them CW again for(int i = 2*n*n; i < 3*n*n; i++){ swapVerts(tri_Angles[i].vert[0], tri_Angles[i].vert[2]); } // --- Forth face --- // We take the original equilateral triangle face. // First we translate it so its' lower right corner is at the origin // Then we bend it -70.528779° = -arccos(1/3) around its right edge.. x_Lat = glm::translate(glm::vec3(-1.0f, 0.0f, 0.0f)); Spin = glm::rotate( -tetra_Dihedral, glm::vec3(-0.5f,0.866025f,0.0f)); for(int i = 0; i < n*n; i++){ for(int j = 0; j < 3; j++){ // This is the forth face so triangle indecies // run from 3n² to 4n² tri_Angles[3*n*n + i].vert[j] = Spin*x_Lat*tri_Angles[i].vert[j]; } } //need to make it CW again for(int i = 3*n*n; i < 4*n*n; i++){ swapVerts(tri_Angles[i].vert[0], tri_Angles[i].vert[2]);v } // We now have the complete tetrahedron but its' base is not horizontal. // Lets set it flat in the xz plane and center it at the origin. // put the base in the xz plane: Rotate: 90 - dihedral angle around the // X - axis. Spin = glm::rotate( tetra_Dihedral - half_PI, xaxis); for(int i = 0; i < 4*n*n; i++){ for(int j = 0; j < 3; j++){ Spin*tri_Angles[i].vert[j]; } } // Put the center at the origin, y axis passing through the apex // sqrt(3/8) = 0.6124 is the distance from "top/apex" vertex to center // of a tetrahedron with side = 1 // // 1/2(sqrt(3)) = 0.28867 is the distance from the mid-point of an edge // to the center of a face.a vertex to the center of a side. x_Lat = glm::translate( glm::vec3(-0.5f, -0.6124f, 0.28867f)); for(int i = 0; i < 4*n*n; i++){ for(int j = 0; j < 3; j++){ x_Lat*tri_Angles[i].vert[j]; } } return tri_Angles; } Notes: Oops: Left out std::vector<Triangle> tri_Angles(4*n*n); Should be the first line of the function body! Those last two for loops could and probably should be combined to do a translate*rotate*triangle in one statement, but I have not tried it. All distances are for a tetrahedron with unit side. The sign of the dihedral angle in the rotations was usually determined by trial and error. I.e.; I tried one sign, compiled the code and rendered the tet. If it was wrong I just reversed the sign. The end result is a tetrahedron with its' center at the origin, its' base in the xz plane, and one edge parallel to the X axis. Of the five platonic solids; three (tetrahedron, octahedron, icosahedron) are composed of equilateral triangle faces. One of square faces (cube). And one of pentagon faces (dodecahedron). Two tetrahedrons fit nicely in a cube.
  16. Hello and welcome everyone. I am starting another complete new Tutorial on 3d modelling and animation on blender Please comment what types of chapter could i include to make it complete from very beginning to exper
  17. Dimitri Lozovoy

    Mobile Voxyc Can Now Edit 3D Scenes On Android

    The mobile editor for Voxyc, a voxel-focused open-source game engine in development, can now edit 3D scenes on Android. Right in the app, you can create voxel chunks and combine them with models and sprites. You can import files right from the menu and then assign textures, move and resize them with a few button presses. All imported objects can be animated with Lua scripts. The resulting scenes can be used in games created with Voxyc, but since the project is open-source, export to other formats and engines can be and are expected to be developed. The app is one of the first that allows level creation on the go. You can work wherever inspiration strikes. Any dull moment can now be used productively, which is important for small indie teams that lack resources or work after-hours or on weekends. Using your device's camera to make textures and inserting them right into the scene is also convenient. The app is aimed at people who work on games independently and, perhaps after having already spent hours at their desk job, do not wish to be tied down to a chair and monitor. I find that using the app on a tablet is most convenient. Although the engine and the editor have come a long way in the last year, at this time, I am the only developer on the project. The editor and the engine are still missing some essential features, and I am looking for developers with whom I can share code. The codebase is cross-platform C++ and target platforms are Android, iOS, Windows, Mac, OpenVR, GearVR, Daydream and others. Voxyc editor for Android on Google Play Engine source code on GitHub Gamedev project link
  18. Dimitri Lozovoy

    Mobile Voxyc Can Now Edit 3D Scenes On Android

    The mobile editor for Voxyc, a voxel-focused open-source game engine in development, can now edit 3D scenes on Android. Right in the app, you can create voxel chunks and combine them with models and sprites. You can import files right from the menu and then assign textures, move and resize them with a few button presses. All imported objects can be animated with Lua scripts. The resulting scenes can be used in games created with Voxyc, but since the project is open-source, export to other formats and engines can be and are expected to be developed. The app is one of the first that allows level creation on the go. You can work wherever inspiration strikes. Any dull moment can now be used productively, which is important for small indie teams that lack resources or work after-hours or on weekends. Using your device's camera to make textures and inserting them right into the scene is also convenient. The app is aimed at people who work on games independently and, perhaps after having already spent hours at their desk job, do not wish to be tied down to a chair and monitor. I find that using the app on a tablet is most convenient. Although the engine and the editor have come a long way in the last year, at this time, I am the only developer on the project. The editor and the engine are still missing some essential features, and I am looking for developers with whom I can share code. The codebase is cross-platform C++ and target platforms are Android, iOS, Windows, Mac, OpenVR, GearVR, Daydream and others. Voxyc editor for Android on Google Play Engine source code on GitHub Gamedev project link View full story
  19. Hello! During the implementation of SSLR, I ran into a problem: only objects that are far from the reflecting surface are reflected. For example, as seen in the screenshot, this is a lamp and angel wings. I give the code and screenshots below. #version 330 core uniform sampler2D normalMap; // in view space uniform sampler2D depthMap; // in view space uniform sampler2D colorMap; uniform sampler2D reflectionStrengthMap; uniform mat4 projection; uniform mat4 inv_projection; in vec2 texCoord; layout (location = 0) out vec4 fragColor; vec3 calcViewPosition(in vec2 texCoord) { // Combine UV & depth into XY & Z (NDC) vec3 rawPosition = vec3(texCoord, texture(depthMap, texCoord).r); // Convert from (0, 1) range to (-1, 1) vec4 ScreenSpacePosition = vec4(rawPosition * 2 - 1, 1); // Undo Perspective transformation to bring into view space vec4 ViewPosition = inv_projection * ScreenSpacePosition; ViewPosition.y *= -1; // Perform perspective divide and return return ViewPosition.xyz / ViewPosition.w; } vec2 rayCast(vec3 dir, inout vec3 hitCoord, out float dDepth) { dir *= 0.25f; for (int i = 0; i < 20; i++) { hitCoord += dir; vec4 projectedCoord = projection * vec4(hitCoord, 1.0); projectedCoord.xy /= projectedCoord.w; projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5; float depth = calcViewPosition(projectedCoord.xy).z; dDepth = hitCoord.z - depth; if(dDepth < 0.0) return projectedCoord.xy; } return vec2(-1.0); } void main() { vec3 normal = texture(normalMap, texCoord).xyz * 2.0 - 1.0; vec3 viewPos = calcViewPosition(texCoord); // Reflection vector vec3 reflected = normalize(reflect(normalize(viewPos), normalize(normal))); // Ray cast vec3 hitPos = viewPos; float dDepth; float minRayStep = 0.1f; vec2 coords = rayCast(reflected * minRayStep, hitPos, dDepth); if (coords != vec2(-1.0)) fragColor = mix(texture(colorMap, texCoord), texture(colorMap, coords), texture(reflectionStrengthMap, texCoord).r); else fragColor = texture(colorMap, texCoord); } Screenshot: colorMap: normalMap: depthMap: I will be grateful for help
  20. jb-dev

    Menu V2

    From the album: Vaporwave Roguelite

    Another version of the main menu. This one has a more complete skybox. I'm not sure if it'll be a good idea to use the same shade on the actual Levels skyboxes...
  21. Last week started with some kind of epiphany: I've kinda forgotten the idea of the iterative top-down development of Agile development, which is sad. So after a bit of reflexion, I've decided that it was time to start building stuff like menus, save files and playable characters. This way I could ship a playable alpha quicker, meaning that I could start getting monetary funds sooner. But anyway, let's get right to it! New Shader Beforehand, let me show you my newest shader. This one is supposed to mimic Memphis-like designs. The name "Memphis" comes from the "Memphis Group", an Italian designer group that tried to design THE design of the decade (which coincidently was the 80's). This design was mainly expressed through furniture, although it was still used in many other media. Here are some examples: (Fun fact: most furniture made by the group was actually bought by David Bowe for some reason. By far he had the most exhaustive collection.) But anyway, here's the shader: The shader is supposed to represent a rough texture typically found in many Memphis designs like so: As for the actual shader, I've first experimented with that kind of noise while making splash screens mockups in Blender. Here's the original mockup: (Notice the green bar on the left) This was achieved by using the Musgrave cycles node. The main gist is to use a Perlin noise to which we apply different types of filter to change their appearance to match the desired texture. So I've figured that if I wanted to translate this shader in Unity I needed to take a look at blender's source code, which is coincidently open. Here's the final shader code: float4 mod(float4 x, float4 y) { return x - y * floor(x / y); } float4 mod289(float4 x) { return x - floor(x / 289.0) * 289.0; } float4 permute(float4 x) { return mod289(((x*34.0)+1.0)*x); } float2 fade(float2 t) { return t*t*t*(t*(t*6.0-15.0)+10.0); } float4 taylorInvSqrt(float4 r) { return (float4)1.79284291400159 - r * 0.85373472095314; } // Classic Perlin noise float cnoise(float2 P) { float4 Pi = floor(P.xyxy) + float4(0.0, 0.0, 1.0, 1.0); float4 Pf = frac (P.xyxy) - float4(0.0, 0.0, 1.0, 1.0); Pi = mod289(Pi); // To avoid truncation effects in permutation float4 ix = Pi.xzxz; float4 iy = Pi.yyww; float4 fx = Pf.xzxz; float4 fy = Pf.yyww; float4 i = permute(permute(ix) + iy); float4 gx = frac(i / 41.0) * 2.0 - 1.0 ; float4 gy = abs(gx) - 0.5 ; float4 tx = floor(gx + 0.5); gx = gx - tx; float2 g00 = float2(gx.x,gy.x); float2 g10 = float2(gx.y,gy.y); float2 g01 = float2(gx.z,gy.z); float2 g11 = float2(gx.w,gy.w); float4 norm = taylorInvSqrt(float4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); g00 *= norm.x; g01 *= norm.y; g10 *= norm.z; g11 *= norm.w; float n00 = dot(g00, float2(fx.x, fy.x)); float n10 = dot(g10, float2(fx.y, fy.y)); float n01 = dot(g01, float2(fx.z, fy.z)); float n11 = dot(g11, float2(fx.w, fy.w)); float2 fade_xy = fade(Pf.xy); float2 n_x = lerp(float2(n00, n01), float2(n10, n11), fade_xy.x); float n_xy = lerp(n_x.x, n_x.y, fade_xy.y); return 2.3 * n_xy; } /* Noise Bases */ float safeNoise(fixed4 p) { return cnoise(p); } float noiseMusgraveHeteroTerrain(fixed4 p, float H, float lacunarity, float octaves, float offset) { float value, increment, rmd; float pwHL = pow(lacunarity, -H); float pwr = pwHL; int i; /* first unscaled octave of function; later octaves are scaled */ value = safeNoise(p) - offset; p *= lacunarity; for (i = 1; i < (int)octaves; ++i) { increment = (safeNoise(p) + offset) * pwr * value; value += increment; pwr *= pwHL; p *= lacunarity; } rmd = octaves - floor(octaves); if (rmd != 0.0) { increment = (safeNoise(p) + offset) * pwr * value; value += rmd * increment; } return value; } fixed4 frag(v2f IN, UNITY_VPOS_TYPE screenPos : VPOS) : SV_Target { half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; fixed2 g_Resolution = _ScreenParams.xy; float factor = -IN.texcoord.y + 1; float dimension = max(_NoiseDimensions, 1e-5); float octaves = clamp(_NoiseDetails, 0.0, 16.0); float lacunarity = max(_NoiseLacunarty, 1e-5); fixed4 p = screenPos; p = p / _NoiseScale; float intensity = 1.0; float offset = smoothstep(1, 0,factor); color.rgb = lerp(color.rgb, _NoiseColor.rgb, saturate(intensity * noiseMusgraveHeteroTerrain(p, dimension, lacunarity, octaves, offset))); return color; } The Menus Then the next big thing was to create different menus in the game. In order to achieve a somewhat proper menu navigation, I've first created a simple navigation flow chart that tells what is the flow between two screens. For example, the player firstly goes through the Title screen, then goes to the main menu and so on. As for the actual implementation, I've decided to use the State design pattern. This way I can easily create simple flows between two screen. First, I've got an AbstractMenuState class: using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public abstract class AbstractMenuState : MonoBehaviour { public AbstractMenuState m_nextMenu; public AbstractMenuState m_previousMenu; public Animator m_menuAnimator; protected GameObject m_menu; public GameObject menu { get { if (!m_menu) { m_menu = transform.GetChild(0).gameObject; if (!m_menuAnimator) { m_menu.GetComponent<Animator>(); } } return m_menu; } } // Show the menu public virtual bool ShowMenu() { menu.gameObject.SetActive(true); m_menuAnimator.SetBool(MenuState.instance.openParameterId, true); selected = firstSelectable; return true; } // Hide the menu public virtual bool HideMenu() { m_menuAnimator.SetBool(MenuState.instance.openParameterId, false); StartCoroutine("DisableMenuDelayed"); return true; } // Things to do when we procede to the next menu public virtual void OnNext() { } // Things to do when we return to the previous menu public virtual void OnPrevious() { } IEnumerator DisableMenuDelayed() { bool closedStateReached = false; bool wantToClose = true; MenuState instance = MenuState.instance; // We're disableing the menu once its animation transition is done while (!closedStateReached && wantToClose) { if (!m_menuAnimator.IsInTransition(0)) { closedStateReached = m_menuAnimator.GetCurrentAnimatorStateInfo(0).IsName(instance.closedStateName); } wantToClose = !m_menuAnimator.GetBool(instance.openParameterId); yield return new WaitForEndOfFrame(); } if (wantToClose) { m_menu.gameObject.SetActive(false); } } public GameObject firstSelectable { get { // We search for the first selectable child Selectable[] selectables = m_menu.gameObject.GetComponentsInChildren<Selectable>(true); for (int i = 0, length = selectables.Length; i < length; ++i) { Selectable selectable = selectables[i]; if (selectable.IsActive() && selectable.IsInteractable()) { return selectable.gameObject; } } return null; } } public GameObject selected { set { //Select the GameObject. EventSystem.current.SetSelectedGameObject(value); //If we are using the keyboard right now, that's all we need to do. var standaloneInputModule = EventSystem.current.currentInputModule as StandaloneInputModule; if (standaloneInputModule == null) { //Since we are using a pointer device, we don't want anything selected. //But if the user switches to the keyboard, we want to start the navigation from the provided game object. //So here we set the current Selected to null, so the provided gameObject becomes the Last Selected in the EventSystem. EventSystem.current.SetSelectedGameObject(null); } } } } Then I've also got a MenuState MonoBehavoir that is composed of an AbstractMenuState instance: using System; using System.Collections; using System.Collections.Generic; using UnityEngine; // This is a Singleton public class MenuState : MonoBehaviour { public static MenuState instance; private bool isReady = false; public AbstractMenuState m_currentMenu; /// <summary> /// Awake is called when the script instance is being loaded. /// </summary> void Awake() { // Setup singletion if (instance == null) { instance = this; } else if (instance != this) { Destroy(gameObject); } DontDestroyOnLoad(gameObject); isReady = true; } const string OPEN_TRANSITION_NAME = "Open"; const string CLOSED_STATE_NAME = "Closed"; private int m_openParameterId; public int openParameterId { get { return m_openParameterId; } } public string closedStateName { get { return CLOSED_STATE_NAME; } } /// <summary> /// This function is called when the object becomes enabled and active. /// </summary> void OnEnable() { //We cache the Hash to the "Open" Parameter, so we can feed to Animator.SetBool. m_openParameterId = Animator.StringToHash(OPEN_TRANSITION_NAME); //If set, open the initial Screen now. if(m_currentMenu) { m_currentMenu.ShowMenu(); } } // Proceding to the next menu public void NextMenu() { AbstractMenuStrategy next = m_currentMenu.m_nextMenu; if (next != null) { m_currentMenu.OnNext(); m_currentMenu.HideMenu(); next.ShowMenu(); m_currentMenu = next; } } // Returning to the previous menu public void PreviousMenu() { AbstractMenuStrategy previous = m_currentMenu.m_previousMenu; if (previous != null) { m_currentMenu.OnPrevious(); m_currentMenu.HideMenu(); previous.ShowMenu(); m_currentMenu = previous; } } } When the player clicks an OK button (for example), then the NextMenu() function of the MenuState is called. This internally calls the Show/Hide function of the needed AbstractMenuState and so on. The same thing is true for any "Cancel" type of button, but using the PreviousMenu() function instead of the NextMenu() ones. Because I'm using Unity, I can then just drag and drop each AbstractMenuState instance the m_previousMenu and m_nextMenu fields to recreate my flowchart. I can even technically set these dynamically based on which button was pressed (like in the main menu screen for example) So let's get right into each menu then! Title Screen This is the title screen. The player just presses any keys to pass right through it and go straight to the main menu. Main Menu This is the main menu. The player can navigate to different screens by pressing one of the menu's buttons. Let's see what each button do. Quick Play This button is quite simple; it quickly prepares a game by reusing previously used parameters. This way the player can quickly get in the game with just one click. This automatically picks the last used savefile and character and puts the player directly at the confirm screen. If it's the first time the game is launched, then the first savefile and the default character are used. This is kinda useful. You only need two clicks and you're ready to go! Play This one is the long version of the Quick Play button. The player then needs to pick a save file from 4 different saves. Right after that, the player chooses a playable character and is then put right at the confirm screen. Options This is self-descriptive. It puts the player at the options screen. Exit This button spawns a quitting prompt. If the player chooses "Yes", then the game quits. Otherwise the prompt closes. Savefile Screen This screen is where the player can choose which save files to use. A savefile holds many different types of pertinent statistics and information (Things like unlocks, run statistics and game completion). It also holds things like the last used character and so on. At this screen, the player will be able to do many different types of savefile manipulation like copy and erase. As of now, these operations aren't implemented, so only the OK button works. Before any operation buttons are enabled, the player must select a save file by clicking (or selecting if you use a controller) a specific save file. A selected savefile will have a green checkmark on its upper-right corner. When the player enters the screen the last used savefile is highlighted. If the game is fresh then the first savefile is used. Each save file also shows things like a progression mark and a last used date. I have yet to precise how the progression percentage is calculated, though I have some ideas on how this can be done (maybe thought unlocks and achievements, but I'm not sure yet). The player can also go back to the main menu using the "Cancel" button. Once the savefile is chosen, the screens translate to the character selection screen. Character Selection Screen This screen is where the player chooses its characters. Each character comes with different stats, focus and equipment. Each of these characteristics can be inspected through the white panel in the lower half of the screen. Like how these components behave in the pause menu, some of these also have tooltips. The characters themselves are laid in a circle formation. The layout system is dynamic enough to have n playable characters, and it's using the game object's children to do all of the layings. The currently selected playable character has a thick outline and it often the one closest to the camera. Also, the currently selected character is determined by the selected savefiles' last used character. If the data is missing then it goes to the default character. In order to change the currently selected character, the player simply uses both left and right arrows at both sides of the screen. This simply turns the contraption by a given angle (calculated from the amount of object present in the root game object). This changes the outline so that it'll follow the currently selected character. Again, the player can either go back to the save file screen or proceed to the confirmation screen. Confirmation Screen This is the last screen before starting the run. In this screen, the player can review its run parameters (like the used save file and the selected character). We can also set the generation seed at this point. As of now if the player chooses to go back then he goes all the way back to the main menu... I'm not sure if it's a better idea if we store from which screen the player came from and use this to send it back to the relevant screen. Options Screen This is where the options will be displayed. I didn't have the time to complete it yet, but it's still accessible. There will be different types of settings typical of any modern games, like graphical settings and whatnot. I've also planned to show statistic here. However, I'm not sure if I should have different tabs/view for each saves file... Technically I could place the save file selection right before the main menu and only show one statistics screen, but I'm not sure yet. That's about it for screens. Minor upgrades Because of the new shader, I've also changed some of the pause menus to use the new shader: There are also some GUI elements that also use these, like the aesthetics lines and health bars... I cant show them just yet because the menu kinda blocks the access to levels right now... I've implemented a playable character class that stores any character specific things like equipment and such; Also, save files are in. There's a simple serialization/deserialization going on with these: I'm not sure when to save though. Right now it's after each savefile changes (like when the player uses a crystal and whatnot). I've also added a GUI shader that uses a special "Hard Light" blend mode when dealing with GUI element textures. Normally Unity uses chromatic multiplication to blend GUI textures with colours. This, however, makes any pure white pixels on the texture take the actual GUI colour; (Hard Light on the left Left, Multiplication on the right) I've added a bunch of textures on buttons and panels. This really looks AESTHETIC now. I've added a normal mapped variant of the AtlasShader. This is quite useful for the menus' statues. Speaking of which these are actually still technically low poly (under 600 tris each!). Their normal maps were baked from high poly models with over 2M verts! Needless to say that Blender crashed a bunch of times while manipulating these... I've finally switched some GUI components to used the Unity's Graphic class rather than coding everything by hand and manually calling the CanvasRenderer. This makes the GUI element's code much cleaner and readable! Next Week If everything goes to plan the game will be in a playable state by beginning 2019 (or so I hope). There's still some work to do with menus... For example, the options screen isn't fully there and so far no runs can be started. I didn't complete the actual level completion, and this might be a good thing to do afterwards... Afterwards, I think I'll be able to code at least one dummy boss, with a somewhat simple attack pattern and whatnot. After it's the usual suspects: Relics, Capacities, Activated items, Equipment... The list goes on.
  22. The algorithm of POM link:https://developer.amd.com/wordpress/media/2012/10/Tatarchuk-POM.pdf This PPT got the neat effect at the oblique angle: What I got more like a relief mapping (maxstep 32, minstep 8): here are some of my code snip: int NumberSteps = (int)lerp(MaxSteps, MinSteps, dot(ViewWS, NormalWS)); float CurrHeight = 0.0; float StepSize = 1.0 / (float)NumberSteps; float PrevHeight = 1.0; float NextHeight = 0.0; int StepIndex = 0; bool Condition = true; float2 TexOffsetPerStep = StepSize * ParallaxOffsetTS; float2 TexCurrentOffset = TexCoord; float CurrentBound = 1.0; float ParallaxAmount = 0.0; float2 Pt1 = 0; float2 Pt2 = 0; float2 TexOffset2 = 0; while(StepIndex < NumberSteps) { TexCurrentOffset -= TexOffsetPerStep; CurrHeight = Texture2DSampleGrad(BumpMap,BumpMapSampler, TexCurrentOffset, InDDX, InDDY).x; CurrentBound -= StepSize; if(CurrHeight > CurrentBound) { Pt1 = float2(CurrentBound, CurrHeight); Pt2 = float2(CurrentBound+StepSize, PrevHeight); TexOffset2 = TexCurrentOffset - TexOffsetPerStep; StepIndex = NumberSteps + 1; } else { StepIndex++; PrevHeight = CurrHeight; } } float Delta2 = Pt2.x - Pt2.y; float Delta1 = Pt1.x - Pt1.y; ParallaxAmount = (Pt1.x*Delta2 - Pt2.x*Delta1)/(Delta2 - Delta1); float2 ParallaxOffset = ParallaxOffsetTS * (1.0 - ParallaxAmount); float2 TexSampleBase = TexCoord - ParallaxOffset; TexSampleCoord = TexSampleBase; Is something I missing here? Thanks a lot!
  23. Been struggling to find the best way to create LOD's for a delaunay triangulated terrain mesh. Currently I triangulate the entire area, then have a simple chunk system where triangles are assigned to chunks by their center. Naturally this results in the jagged edges as shown in the pic, so it's nearly impossible I think to create LOD's from that. But triangulating by chunks has it's own set of issues. Mainly that chunk edges would not match exactly. And even if they did, it would be visible in a bad way. I haven't found any free mesh decimation tools that can retain the edges correctly. Plus any tools here need to integrate into a procedural pipeline in Unity. I was thinking maybe there was some way to handle this in a shader. I'm using a single global texture with planar mapping for the terrain, so I was thinking maybe I could use a stencil buffer in some way to get the pixels representing the gaps in the LOD's? Any ideas appreciated.
  24. Hello everyone! I want to remake a Direct3D 11 C++ application for Android. I'm not familiar with any engines or libraries on the current time, only with pure Direct3D and OpenGL (including OpenGL ES), but I'm ready to learn one. Which library/engine should I choose? On the current time I'm considering LibGDX for this purpose, but I heard that it's not very suitable for 3D. I was also considering OpenGL ES (with Java) but I think it will be tricky to improve the game in this case (I'm planning to use an animated character, particles in the game). Performance is one of the main requirements to the game. I would also wish to have a possibility to compile the code for iOS or easy remake the code for this platform. Thanks in advance!
  25. But somehow continuity is reduced from 2 to 1 on vertices with valence != 4. When I repeat the subdivision (in blender), most vertices have a valence of 4. So is this c1 just a point? I mean I do not observe any discontinuities with CookTorr shading. I think the size of the highlight would have to suddenly change. Furthermore, I could not find any application of c3. Looking into physics: roller-coaster and car racing: c1 is fun and works. c2 is for comfort. Also fluid dynamics solver should not really depend on continuity. Okay, they may slow down without enough of it. Additionally having "crease", is there any reason to miss rational b-splines? I thought about increasing the order of the Polynoms around vertices with valence != 4, thinking that maybe one order is being eaten in the process. Then I would not need to hide these bad spots by moving them into the armpits of my model. I would trade in the extra effort of some more control points (a finer base mesh). But the math behind these vertices (what I find in google) seems to be overly complicated. Nonrational b-splines are straight forward expansion of nonrational splines, which in turn are generated by using a sliding window smoothing filter on a sequence of delta distributions. Lots of publications seem to frown upon the recursive algorithm. Lisp has told me that recursion is good. Also I do not get why hardware should generally have a problem with that. Feels like a smoke screen to me.