Sign in to follow this  
nullsmind

OpenGL Any luck with OpenGL using C#?

Recommended Posts

I sucessfully compiled CSGL with C# using NeHe's tutorials, but the way its done doesn't allow form support, considering the top keywords OpenGLControl and base(). Is it just this code, or is there a better OpenGL port for C#?
#region Using Clauses
using System;
using System.Drawing;
using System.Windows.Forms;
using CsGL.OpenGL;
#endregion

namespace Lesson1
{
    public class OurView : OpenGLControl
    {
        public OurView() : base()
        {
            this.KeyDown += new KeyEventHandler(OurView_OnKeyDown);
        }

        protected void OurView_OnKeyDown(object Sender, KeyEventArgs kea)
        {
            //if escape was pressed exit the application
            if (kea.KeyCode == Keys.Escape)
            {
                Application.Exit();
            }
        }
        
        public override void glDraw()
        {
            GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
            GL.glLoadIdentity(); 
        }

        protected override void InitGLContext()
        {
            GL.glShadeModel(GL.GL_SMOOTH);							// Enable Smooth Shading
            GL.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);				// Black Background
            GL.glClearDepth(1.0f);									// Depth Buffer Setup
            GL.glEnable(GL.GL_DEPTH_TEST);							// Enables Depth Testing
            GL.glDepthFunc(GL.GL_LEQUAL);								// The Type Of Depth Testing To Do
            GL.glHint(GL.GL_PERSPECTIVE_CORRECTION_HINT, GL.GL_NICEST);	// Really Nice Perspective Calculations
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            Size s = Size;

            GL.glMatrixMode(GL.GL_PROJECTION);
            GL.glLoadIdentity();
            GL.gluPerspective(45.0f, (double)s.Width / (double)s.Height, 0.1f, 100.0f);
            GL.glMatrixMode(GL.GL_MODELVIEW);
            GL.glLoadIdentity();
        }
    }

    public class MainForm : System.Windows.Forms.Form	// Will show us the OpenGL window
    {
        private Lesson1.OurView view;

        public MainForm()
        {
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
            this.ClientSize = new System.Drawing.Size(640, 480);
            this.Name = "MainForm";
            this.Text = "NeHe's Lesson 1 in C# (by Joachim Rohde)";
            this.view = new Lesson1.OurView();			// view
            this.view.Parent = this;
            this.view.Dock = DockStyle.Fill; // Will fill whole form
        }

        static void Main()
        {
            Application.Run(new MainForm());
        }
    }
}



[Edited by - nullsmind on April 3, 2006 10:50:14 PM]

Share this post


Link to post
Share on other sites
What do you mean by "doesn't allow form support?"

As an alternative to CSGL, you might look at the Tao Framework. It includes bindings for OpenGL, GLFW, SDL, and a bunch of other libraries.

Share this post


Link to post
Share on other sites
Thanks, Dave, I downloaded that and compiled NeHe's first tutorial fine. The same problem exists, though. I'd like to have access to Visual Studio's IDE form design, but with NeHe's tutorial, it has this line...

private static Form form;

So, instead of the drawing taking place on Form1, it's doing the following:


public sealed class Lesson01 : Form
{
// --- Fields ---
#region Private Static Fields
private static IntPtr hDC; // Private GDI Device Context
private static IntPtr hRC; // Permanent Rendering Context
private static Form form; // Our Current Windows Form





So it's basically ignoring that Form1 ever existed. I wouldn't be able to throw the rendering into a Form1 panel, for example because it's somehow running independently from that. So why not replace Lesson1 with Form1? Surely that would solve it. Although it compiles fine, what I do in Form1's form designer doesn't show up on execution, such as centering the window. The program still seems to run independently. I'll experiment around some more today, but any suggestions would be great. I basically need OpenGL and my form designer to interact together using C# w/ VS 05.

Current code:

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Tao.OpenGl;
using Tao.Platform.Windows;

namespace NeHe
{
public sealed class Form1 : Form
{
// --- Fields ---
#region Private Static Fields
private static IntPtr hDC; // Private GDI Device Context
private static IntPtr hRC; // Permanent Rendering Context
private static Form form; // Our Current Windows Form
private static bool[] keys = new bool[256]; // Array Used For The Keyboard Routine
private static bool active = true; // Window Active Flag, Set To True By Default
private static bool fullscreen = true; // Fullscreen Flag, Set To Fullscreen Mode By Default
private static bool done = false; // Bool Variable To Exit Main Loop
#endregion Private Static Fields

// --- Constructors & Destructors ---
#region Lesson01
/// <summary>
/// Creates a new instance.
/// </summary>
public Form1()
{
this.CreateParams.ClassStyle = this.CreateParams.ClassStyle | // Redraw On Size, And Own DC For Window.
User.CS_HREDRAW | User.CS_VREDRAW | User.CS_OWNDC;
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); // No Need To Erase Form Background
this.SetStyle(ControlStyles.DoubleBuffer, true); // Buffer Control
this.SetStyle(ControlStyles.Opaque, true); // No Need To Draw Form Background
this.SetStyle(ControlStyles.ResizeRedraw, true); // Redraw On Resize
this.SetStyle(ControlStyles.UserPaint, true); // We'll Handle Painting Ourselves

this.Activated += new EventHandler(this.Form_Activated); // On Activate Event Call Form_Activated
this.Closing += new CancelEventHandler(this.Form_Closing); // On Closing Event Call Form_Closing
this.Deactivate += new EventHandler(this.Form_Deactivate); // On Deactivate Event Call Form_Deactivate
this.KeyDown += new KeyEventHandler(this.Form_KeyDown); // On KeyDown Event Call Form_KeyDown
this.KeyUp += new KeyEventHandler(this.Form_KeyUp); // On KeyUp Event Call Form_KeyUp
this.Resize += new EventHandler(this.Form_Resize); // On Resize Event Call Form_Resize
}
#endregion Lesson01

// --- Entry Point ---
#region Main(string[] commandLineArguments)
/// <summary>
/// The application's entry point.
/// </summary>
/// <param name="commandLineArguments">
/// Any supplied command line arguments.
/// </param>
[STAThread]
public static void Main(string[] commandLineArguments)
{
// Ask The User Which Screen Mode They Prefer
if (MessageBox.Show("Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",
MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
{
fullscreen = false; // Windowed Mode
}

// Create Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework", 640, 480, 16, fullscreen))
{
return; // Quit If Window Was Not Created
}

while (!done)
{ // Loop That Runs While done = false
Application.DoEvents(); // Process Events

if (active && (form != null))
{ // Program Active?
if (keys[(int)Keys.Escape])
{ // Was ESC Pressed?
done = true; // ESC Signalled A Quit
}
else
{ // Not Time To Quit, Update Screen
DrawGLScene(); // Draw The Scene
Gdi.SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}

if (keys[(int)Keys.F1])
{ // Is F1 Being Pressed?
keys[(int)Keys.F1] = false; // If So Make Key false
KillGLWindow(); // Kill Our Current Window
fullscreen = !fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's OpenGL Framework", 640, 480, 16, fullscreen))
{
return; // Quit If Window Was Not Created
}
done = false; // We're Not Done Yet
}
}

// Shutdown
KillGLWindow(); // Kill The Window
return; // Exit The Program
}
#endregion Main(string[] commandLineArguments)

// --- Private Static Methods ---
#region bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag)
/// <summary>
/// Creates our OpenGL Window.
/// </summary>
/// <param name="title">
/// The title to appear at the top of the window.
/// </param>
/// <param name="width">
/// The width of the GL window or fullscreen mode.
/// </param>
/// <param name="height">
/// The height of the GL window or fullscreen mode.
/// </param>
/// <param name="bits">
/// The number of bits to use for color (8/16/24/32).
/// </param>
/// <param name="fullscreenflag">
/// Use fullscreen mode (<c>true</c>) or windowed mode (<c>false</c>).
/// </param>
/// <returns>
/// <c>true</c> on successful window creation, otherwise <c>false</c>.
/// </returns>
private static bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag)
{
int pixelFormat; // Holds The Results After Searching For A Match
fullscreen = fullscreenflag; // Set The Global Fullscreen Flag
form = null; // Null The Form

GC.Collect(); // Request A Collection
// This Forces A Swap
Kernel.SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1);

if (fullscreen)
{ // Attempt Fullscreen Mode?
Gdi.DEVMODE dmScreenSettings = new Gdi.DEVMODE(); // Device Mode
// Size Of The Devmode Structure
dmScreenSettings.dmSize = (short)Marshal.SizeOf(dmScreenSettings);
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields = Gdi.DM_BITSPERPEL | Gdi.DM_PELSWIDTH | Gdi.DM_PELSHEIGHT;

// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (User.ChangeDisplaySettings(ref dmScreenSettings, User.CDS_FULLSCREEN) != User.DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox.Show("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?", "NeHe GL",
MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
{
fullscreen = false; // Windowed Mode Selected. Fullscreen = false
}
else
{
// Pop up A Message Box Lessing User Know The Program Is Closing.
MessageBox.Show("Program Will Now Close.", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return false; // Return false
}
}
}

form = new Form1(); // Create The Window

if (fullscreen)
{ // Are We Still In Fullscreen Mode?
form.FormBorderStyle = FormBorderStyle.None; // No Border
Cursor.Hide(); // Hide Mouse Pointer
}
else
{ // If Windowed
form.FormBorderStyle = FormBorderStyle.Sizable; // Sizable
Cursor.Show(); // Show Mouse Pointer
}

form.Width = width; // Set Window Width
form.Height = height; // Set Window Height
form.Text = title; // Set Window Title

Gdi.PIXELFORMATDESCRIPTOR pfd = new Gdi.PIXELFORMATDESCRIPTOR(); // pfd Tells Windows How We Want Things To Be
pfd.nSize = (short)Marshal.SizeOf(pfd); // Size Of This Pixel Format Descriptor
pfd.nVersion = 1; // Version Number
pfd.dwFlags = Gdi.PFD_DRAW_TO_WINDOW | // Format Must Support Window
Gdi.PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
Gdi.PFD_DOUBLEBUFFER; // Format Must Support Double Buffering
pfd.iPixelType = (byte)Gdi.PFD_TYPE_RGBA; // Request An RGBA Format
pfd.cColorBits = (byte)bits; // Select Our Color Depth
pfd.cRedBits = 0; // Color Bits Ignored
pfd.cRedShift = 0;
pfd.cGreenBits = 0;
pfd.cGreenShift = 0;
pfd.cBlueBits = 0;
pfd.cBlueShift = 0;
pfd.cAlphaBits = 0; // No Alpha Buffer
pfd.cAlphaShift = 0; // Shift Bit Ignored
pfd.cAccumBits = 0; // No Accumulation Buffer
pfd.cAccumRedBits = 0; // Accumulation Bits Ignored
pfd.cAccumGreenBits = 0;
pfd.cAccumBlueBits = 0;
pfd.cAccumAlphaBits = 0;
pfd.cDepthBits = 16; // 16Bit Z-Buffer (Depth Buffer)
pfd.cStencilBits = 0; // No Stencil Buffer
pfd.cAuxBuffers = 0; // No Auxiliary Buffer
pfd.iLayerType = (byte)Gdi.PFD_MAIN_PLANE; // Main Drawing Layer
pfd.bReserved = 0; // Reserved
pfd.dwLayerMask = 0; // Layer Masks Ignored
pfd.dwVisibleMask = 0;
pfd.dwDamageMask = 0;

hDC = User.GetDC(form.Handle); // Attempt To Get A Device Context
if (hDC == IntPtr.Zero)
{ // Did We Get A Device Context?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Create A GL Device Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

pixelFormat = Gdi.ChoosePixelFormat(hDC, ref pfd); // Attempt To Find An Appropriate Pixel Format
if (pixelFormat == 0)
{ // Did Windows Find A Matching Pixel Format?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Find A Suitable PixelFormat.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

if (!Gdi.SetPixelFormat(hDC, pixelFormat, ref pfd))
{ // Are We Able To Set The Pixel Format?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Set The PixelFormat.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

hRC = Wgl.wglCreateContext(hDC); // Attempt To Get The Rendering Context
if (hRC == IntPtr.Zero)
{ // Are We Able To Get A Rendering Context?
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Create A GL Rendering Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

if (!Wgl.wglMakeCurrent(hDC, hRC))
{ // Try To Activate The Rendering Context
KillGLWindow(); // Reset The Display
MessageBox.Show("Can't Activate The GL Rendering Context.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

form.Show(); // Show The Window
form.TopMost = true; // Topmost Window
form.Focus(); // Focus The Window

if (fullscreen)
{ // This Shouldn't Be Necessary, But Is
Cursor.Hide();
}
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen

if (!InitGL())
{ // Initialize Our Newly Created GL Window
KillGLWindow(); // Reset The Display
MessageBox.Show("Initialization Failed.", "ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}

return true; // Success
}
#endregion bool CreateGLWindow(string title, int width, int height, int bits, bool fullscreenflag)

#region bool DrawGLScene()
/// <summary>
/// Here's where we do all the drawing.
/// </summary>
/// <returns>
/// <c>true</c> on successful drawing, otherwise <c>false</c>.
/// </returns>
private static bool DrawGLScene()
{
Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
Gl.glLoadIdentity(); // Reset The Current Modelview Matrix
return true;
}
#endregion bool DrawGLScene()

#region bool InitGL()
/// <summary>
/// All setup for OpenGL goes here.
/// </summary>
/// <returns>
/// <c>true</c> on successful initialization, otherwise <c>false</c>.
/// </returns>
private static bool InitGL()
{
Gl.glShadeModel(Gl.GL_SMOOTH); // Enable Smooth Shading
Gl.glClearColor(0, 0, 0, 0.5f); // Black Background
Gl.glClearDepth(1); // Depth Buffer Setup
Gl.glEnable(Gl.GL_DEPTH_TEST); // Enables Depth Testing
Gl.glDepthFunc(Gl.GL_LEQUAL); // The Type Of Depth Testing To Do
Gl.glHint(Gl.GL_PERSPECTIVE_CORRECTION_HINT, Gl.GL_NICEST); // Really Nice Perspective Calculations
return true;
}
#endregion bool InitGL()

#region KillGLWindow()
/// <summary>
/// Properly kill the window.
/// </summary>
private static void KillGLWindow()
{
if (fullscreen)
{ // Are We In Fullscreen Mode?
User.ChangeDisplaySettings(IntPtr.Zero, 0); // If So, Switch Back To The Desktop
Cursor.Show(); // Show Mouse Pointer
}

if (hRC != IntPtr.Zero)
{ // Do We Have A Rendering Context?
if (!Wgl.wglMakeCurrent(IntPtr.Zero, IntPtr.Zero))
{ // Are We Able To Release The DC and RC Contexts?
MessageBox.Show("Release Of DC And RC Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}

if (!Wgl.wglDeleteContext(hRC))
{ // Are We Able To Delete The RC?
MessageBox.Show("Release Rendering Context Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}

hRC = IntPtr.Zero; // Set RC To Null
}

if (hDC != IntPtr.Zero)
{ // Do We Have A Device Context?
if (form != null && !form.IsDisposed)
{ // Do We Have A Window?
if (form.Handle != IntPtr.Zero)
{ // Do We Have A Window Handle?
if (!User.ReleaseDC(form.Handle, hDC))
{ // Are We Able To Release The DC?
MessageBox.Show("Release Device Context Failed.", "SHUTDOWN ERROR",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

hDC = IntPtr.Zero; // Set DC To Null
}

if (form != null)
{ // Do We Have A Windows Form?
form.Hide(); // Hide The Window
form.Close(); // Close The Form
form = null; // Set form To Null
}
}
#endregion KillGLWindow()

#region ReSizeGLScene(int width, int height)
/// <summary>
/// Resizes and initializes the GL window.
/// </summary>
/// <param name="width">
/// The new window width.
/// </param>
/// <param name="height">
/// The new window height.
/// </param>
private static void ReSizeGLScene(int width, int height)
{
if (height == 0)
{ // Prevent A Divide By Zero...
height = 1; // By Making Height Equal To One
}

Gl.glViewport(0, 0, width, height); // Reset The Current Viewport
Gl.glMatrixMode(Gl.GL_PROJECTION); // Select The Projection Matrix
Gl.glLoadIdentity(); // Reset The Projection Matrix
Glu.gluPerspective(45, width / (double)height, 0.1, 100); // Calculate The Aspect Ratio Of The Window
Gl.glMatrixMode(Gl.GL_MODELVIEW); // Select The Modelview Matrix
Gl.glLoadIdentity(); // Reset The Modelview Matrix
}
#endregion ReSizeGLScene(int width, int height)

// --- Private Instance Event Handlers ---
#region Form_Activated
/// <summary>
/// Handles the form's activated event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_Activated(object sender, EventArgs e)
{
active = true; // Program Is Active
}
#endregion Form_Activated

#region Form_Closing(object sender, CancelEventArgs e)
/// <summary>
/// Handles the form's closing event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_Closing(object sender, CancelEventArgs e)
{
done = true; // Send A Quit Message
}
#endregion Form_Closing(object sender, CancelEventArgs e)

#region Form_Deactivate(object sender, EventArgs e)
/// <summary>
/// Handles the form's deactivate event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_Deactivate(object sender, EventArgs e)
{
active = false; // Program Is No Longer Active
}
#endregion Form_Deactivate(object sender, EventArgs e)

#region Form_KeyDown(object sender, KeyEventArgs e)
/// <summary>
/// Handles the form's key down event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_KeyDown(object sender, KeyEventArgs e)
{
keys[e.KeyValue] = true; // Key Has Been Pressed, Mark It As true
}
#endregion Form_KeyDown(object sender, KeyEventArgs e)

#region Form_KeyUp(object sender, KeyEventArgs e)
/// <summary>
/// Handles the form's key down event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_KeyUp(object sender, KeyEventArgs e)
{
keys[e.KeyValue] = false; // Key Has Been Released, Mark It As false
}
#endregion Form_KeyUp(object sender, KeyEventArgs e)

#region Form_Resize(object sender, EventArgs e)
/// <summary>
/// Handles the form's resize event.
/// </summary>
/// <param name="sender">
/// The event sender.
/// </param>
/// <param name="e">
/// The event arguments.
/// </param>
private void Form_Resize(object sender, EventArgs e)
{
ReSizeGLScene(form.Width, form.Height); // Resize The OpenGL Window
}
#endregion Form_Resize(object sender, EventArgs e)

private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(530, 432);
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Form1";
this.ResumeLayout(false);

}
}
}


Share this post


Link to post
Share on other sites
The Tao.Platform.Windows.SimpleOpenGLControl class provides a control that you can use as the target for your OpenGL rendering. You can add this control to a Forms Designer form like any other control.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Forum Statistics

    • Total Topics
      627764
    • Total Posts
      2978976
  • Similar Content

    • By DelicateTreeFrog
      Hello! As an exercise for delving into modern OpenGL, I'm creating a simple .obj renderer. I want to support things like varying degrees of specularity, geometry opacity, things like that, on a per-material basis. Different materials can also have different textures. Basic .obj necessities. I've done this in old school OpenGL, but modern OpenGL has its own thing going on, and I'd like to conform as closely to the standards as possible so as to keep the program running correctly, and I'm hoping to avoid picking up bad habits this early on.
      Reading around on the OpenGL Wiki, one tip in particular really stands out to me on this page:
      For something like a renderer for .obj files, this sort of thing seems almost ideal, but according to the wiki, it's a bad idea. Interesting to note!
      So, here's what the plan is so far as far as loading goes:
      Set up a type for materials so that materials can be created and destroyed. They will contain things like diffuse color, diffuse texture, geometry opacity, and so on, for each material in the .mtl file. Since .obj files are conveniently split up by material, I can load different groups of vertices/normals/UVs and triangles into different blocks of data for different models. When it comes to the rendering, I get a bit lost. I can either:
      Between drawing triangle groups, call glUseProgram to use a different shader for that particular geometry (so a unique shader just for the material that is shared by this triangle group). or
      Between drawing triangle groups, call glUniform a few times to adjust different parameters within the "master shader", such as specularity, diffuse color, and geometry opacity. In both cases, I still have to call glBindTexture between drawing triangle groups in order to bind the diffuse texture used by the material, so there doesn't seem to be a way around having the CPU do *something* during the rendering process instead of letting the GPU do everything all at once.
      The second option here seems less cluttered, however. There are less shaders to keep up with while one "master shader" handles it all. I don't have to duplicate any code or compile multiple shaders. Arguably, I could always have the shader program for each material be embedded in the material itself, and be auto-generated upon loading the material from the .mtl file. But this still leads to constantly calling glUseProgram, much more than is probably necessary in order to properly render the .obj. There seem to be a number of differing opinions on if it's okay to use hundreds of shaders or if it's best to just use tens of shaders.
      So, ultimately, what is the "right" way to do this? Does using a "master shader" (or a few variants of one) bog down the system compared to using hundreds of shader programs each dedicated to their own corresponding materials? Keeping in mind that the "master shaders" would have to track these additional uniforms and potentially have numerous branches of ifs, it may be possible that the ifs will lead to additional and unnecessary processing. But would that more expensive than constantly calling glUseProgram to switch shaders, or storing the shaders to begin with?
      With all these angles to consider, it's difficult to come to a conclusion. Both possible methods work, and both seem rather convenient for their own reasons, but which is the most performant? Please help this beginner/dummy understand. Thank you!
    • By JJCDeveloper
      I want to make professional java 3d game with server program and database,packet handling for multiplayer and client-server communicating,maps rendering,models,and stuffs Which aspect of java can I learn and where can I learn java Lwjgl OpenGL rendering Like minecraft and world of tanks
    • By AyeRonTarpas
      A friend of mine and I are making a 2D game engine as a learning experience and to hopefully build upon the experience in the long run.

      -What I'm using:
          C++;. Since im learning this language while in college and its one of the popular language to make games with why not.     Visual Studios; Im using a windows so yea.     SDL or GLFW; was thinking about SDL since i do some research on it where it is catching my interest but i hear SDL is a huge package compared to GLFW, so i may do GLFW to start with as learning since i may get overwhelmed with SDL.  
      -Questions
      Knowing what we want in the engine what should our main focus be in terms of learning. File managements, with headers, functions ect. How can i properly manage files with out confusing myself and my friend when sharing code. Alternative to Visual studios: My friend has a mac and cant properly use Vis studios, is there another alternative to it?  
    • By ferreiradaselva
      Both functions are available since 3.0, and I'm currently using `glMapBuffer()`, which works fine.
      But, I was wondering if anyone has experienced advantage in using `glMapBufferRange()`, which allows to specify the range of the mapped buffer. Could this be only a safety measure or does it improve performance?
      Note: I'm not asking about glBufferSubData()/glBufferData. Those two are irrelevant in this case.
    • By xhcao
      Before using void glBindImageTexture(    GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format), does need to make sure that texture is completeness. 
  • Popular Now