Cannot change OpenGL textures in C plugin

I’ve been trying to manipulate textures in an OpenGL-based C plugin, as others have done in the past, but I can’t get it working. I have the plugin compiling, and I know the method’s being called as it returns the number of bytes written and that appears right, but the texture remains unchanged. I can also change the texture using the SetPixel() method, but that’s not fast enough for what I’m planning.

I am running the editor (and standalones) with the ‘-force-opengl’ command line option and the menubar’s indicating that I’m running in the correct mode.

The C code for the plugin I’m using is as follows:

#define EXPORT __declspec(dllexport)

#include <GL\gl.h>
#include <stdlib.h>
#include <vector>

extern "C" {
    EXPORT int RebuildTexture(int texture_id, int width, int height, int time)
    {
    	// Set up the memory block storing the RGB info.
        int size = width * height * 3;
	char* bytes = (char*) malloc(size);
	int updated = 0;
	for( int i = 0 ; i < size; i++ )
	{
		bytes[i] = time;
		updated++;
	}

	// Use the memory block to replace the texture.
        glBindTexture(GL_TEXTURE_2D, texture_id);
	glTexSubImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
		GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *)bytes);
        free(bytes);

        return updated;
    }
}

…and I’m building it with the MinGW GCC install using the command…

gcc.exe UnityVideoPlugin.cpp -lopengl32 -static -shared -o UnityVideoPlugin.dll

Finally my C# plugin is

using UnityEngine;
using System.Collections;
using System;
using System.Runtime.InteropServices;

public class UnityVideoPlugin : MonoBehaviour {
	private int frame;

	private Texture2D texture;
	private int width = 512;
	private int height = 512;

	//Lets make our calls from the Plugin
	[DllImport ("UnityVideoPlugin")]
	private static extern int RebuildTexture(
		int texture_id, int width, int height, int time);

	void Start() {
		texture = new Texture2D(width, height, TextureFormat.RGB24, false);
		renderer.material.mainTexture = texture;
                // Test we're able to set colors with SetPixel
		for (int x=0; x< texture.width; x++) {
			for (int y=0; y<texture.height; y++) {
				var color = new Color(x/(float) texture.width, y/(float)texture.height,0);
				texture.SetPixel(x, y, color);
			}	
		}
		texture.Apply();
	}

	void Update () {
		var texture = renderer.material.mainTexture as Texture2D;
		var textureID = texture.GetNativeTextureID();
		frame++;
		var result = RebuildTexture(textureID, width, height, frame % 200);
		print(textureID + "- " + width + " x " + height +", " + frame + " = " + result);
	}
}

Does anyone have any ideas what I’m doing wrong here and how to fix it? Thanks.

You shouldn’t be calling a native method that creates and resubmits a texture on every Update(). I don’t know why it’s at least not working extremely slowly though. Maybe the native function isn’t being run where the GL context Unity is using is active…

If this is on Windows, then your need to run Unity with the -forceopengl flag, as Unity Windows defaults to DirectX.
I used glTexSubImage2D in Unity 3.3 on iOS and can verify it works, but I can’t see anything particularly off about your example unless the formats are off or it’s in DirectX mode.

If you open the Console Log text file are there any reported errors (you can printf in the native plugin, and while it won’t show up on the Unity Console it will in the Console.txt file, so that could help diagnose errors).

Thanks coquifrogs and Ntero for the advice.

I did actually manage to get this working- I moved from trying to use MinGW over to Visual Studio’s compiler and it’s started working. I have no idea why it didn’t work in MinGW, or why I at least didn’t get some error messages, but I’m not planning on spending too long investigating it now. My suspicions are that I was getting something subtly wrong with the way I had to configure MinGW to allow the C++ to be linked from C but I’m not really sure.

This isn’t intended to ultimately be something which is happening every frame by the way, it was just an initial piece of work to get dynamic textures working before the serious work begins. The eventual aim is to use a fast video decode library, probably GPU-accelerated or at least in a different thread, to allow multiple HD-resolution video streams to be used in Unity.

Progress is still being made, although this is a personal project and I’m easily distracted, but hopefully I’ll end up with something which I can show to folks at some point soonish.

I know this thread is stale but I’m curious on how you were able to get either glTexSubImage2D or glTexImage2D to work for updating a texture to the video buffer with the sub code provide in this thread. My tests thus far has resulted in a GL_INVALID_OPERATION before and after the glBindTexture and glTexSubImage2D when using the code provided in this post. I am using Unity 3.5.3, Windows with -force-opengl and Visual Studio 2010. I am alos assuming that no other opengl calls are required in either the plugin or monobehaviour as Unity would appropriate establish all the needed opengl contexts. Any good or bad suggestions?

Very well-timed comment, I’m actually getting back into this now after some time away. I’ll see if I can get a minimal and clean project with this working (it’s tangled with a lot of other experimental things at present) and if so I’ll just upload it and post the link here.

We have just faced the GL_INVALID_OPERATION problem in our project.

Just build a standalone version of your application and force that to OpenGL instead. For some reason it doesn’t seem to work in the editor, I guess it must be a bug or some technical restriction.

Hi there,

I am essentially in the same situation as absurdic just posted.

Molt - I am very interested in seeing your working project if that’s at all possible.

Everything in my plugin appears to work, but in the end my glTexSubImage2D call isn’t doing its job (even building standalone with -force-opengl). I am wondering if there is some configuration in building the plugin code that I’m not doing correctly.

EDIT - Apparently if i change my glTexSubImage2D call to glTexImage2D, it loads my texture in just fine. I figured Unity was calling glTexImage2D at some point before it got to my plugin code but I guess it works in some other way.

Been trying to get this all working again but it’s looking like Unity 3.5 has confused things by introducing the multi-threaded renderer, no longer can we rely on the rendering thread and the processing thread being the same. This, and the current possible workaround, is discussed at http://forum.unity3d.com/threads/127442-Multithreaded-rendering-and-GL.IssuePluginEvent

So far though I’ve been unable to get the GL.IssuePluginEvent working.

Bah.

May just shelve this for a few months in the hopes that Unity 4.0 will provide an easier way to do this type of image manipulation.