LCOV - code coverage report
Current view: top level - Core/Materials - OOShaderUniform.m (source / functions) Hit Total Coverage
Test: coverxygen.info Lines: 0 1 0.0 %
Date: 2025-05-28 07:50:54 Functions: 0 0 -

          Line data    Source code
       1           0 : /*
       2             : 
       3             : OOShaderUniform.m
       4             : 
       5             : 
       6             : Copyright (C) 2007-2013 Jens Ayton
       7             : 
       8             : Permission is hereby granted, free of charge, to any person obtaining a copy
       9             : of this software and associated documentation files (the "Software"), to deal
      10             : in the Software without restriction, including without limitation the rights
      11             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      12             : copies of the Software, and to permit persons to whom the Software is
      13             : furnished to do so, subject to the following conditions:
      14             : 
      15             : The above copyright notice and this permission notice shall be included in all
      16             : copies or substantial portions of the Software.
      17             : 
      18             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      19             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      20             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      21             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      22             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      23             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      24             : SOFTWARE.
      25             : 
      26             : */
      27             : 
      28             : 
      29             : #import "OOShaderUniform.h"
      30             : 
      31             : #if OO_SHADERS
      32             : 
      33             : #import "OOShaderProgram.h"
      34             : #import "OOFunctionAttributes.h"
      35             : #include <string.h>
      36             : #import "OOMaths.h"
      37             : #import "OOOpenGLExtensionManager.h"
      38             : #import "OOShaderUniformMethodType.h"
      39             : 
      40             : 
      41             : @interface OOShaderUniform (OOPrivate)
      42             : 
      43             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram;
      44             : 
      45             : - (void)applySimple;
      46             : - (void)applyBinding;
      47             : 
      48             : @end
      49             : 
      50             : 
      51             : @implementation OOShaderUniform
      52             : 
      53             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram intValue:(GLint)constValue
      54             : {
      55             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
      56             :         if (self != nil)
      57             :         {
      58             :                 type = kOOShaderUniformTypeInt;
      59             :                 value.constInt = constValue;
      60             :         }
      61             :         
      62             :         return self;
      63             : }
      64             : 
      65             : 
      66             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram floatValue:(GLfloat)constValue
      67             : {
      68             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
      69             :         if (self != nil)
      70             :         {
      71             :                 type = kOOShaderUniformTypeFloat;
      72             :                 value.constFloat = constValue;
      73             :         }
      74             :         
      75             :         return self;
      76             : }
      77             : 
      78             : 
      79             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram vectorValue:(GLfloat[4])constValue
      80             : {
      81             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
      82             :         if (self != nil)
      83             :         {
      84             :                 type = kOOShaderUniformTypeVector;
      85             :                 memcpy(value.constVector, constValue, sizeof value.constVector);
      86             :         }
      87             :         
      88             :         return self;
      89             : }
      90             : 
      91             : 
      92             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram colorValue:(OOColor *)constValue
      93             : {
      94             :         if (EXPECT_NOT(constValue == nil))
      95             :         {
      96             :                 [self release];
      97             :                 return nil;
      98             :         }
      99             :         
     100             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
     101             :         if (self != nil)
     102             :         {
     103             :                 type = kOOShaderUniformTypeVector;
     104             :                 value.constVector[0] = [constValue redComponent];
     105             :                 value.constVector[1] = [constValue greenComponent];
     106             :                 value.constVector[2] = [constValue blueComponent];
     107             :                 value.constVector[3] = [constValue alphaComponent];
     108             :         }
     109             :         
     110             :         return self;
     111             : }
     112             : 
     113             : 
     114             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram quaternionValue:(Quaternion)constValue asMatrix:(BOOL)asMatrix
     115             : {
     116             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
     117             :         if (self != nil)
     118             :         {
     119             :                 if (asMatrix)
     120             :                 {
     121             :                         type = kOOShaderUniformTypeMatrix;
     122             :                         value.constMatrix = OOMatrixForQuaternionRotation(constValue);
     123             :                 }
     124             :                 else
     125             :                 {
     126             :                         type = kOOShaderUniformTypeVector;
     127             :                         value.constVector[0] = constValue.x;
     128             :                         value.constVector[1] = constValue.y;
     129             :                         value.constVector[2] = constValue.z;
     130             :                         value.constVector[3] = constValue.w;
     131             :                 }
     132             :         }
     133             :         
     134             :         return self;
     135             : }
     136             : 
     137             : 
     138             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram matrixValue:(OOMatrix)constValue
     139             : {
     140             :         self = [self initWithName:uniformName shaderProgram:shaderProgram];
     141             :         if (self != nil)
     142             :         {
     143             :                 type = kOOShaderUniformTypeMatrix;
     144             :                 value.constMatrix = constValue;
     145             :         }
     146             :         
     147             :         return self;
     148             : }
     149             : 
     150             : 
     151             : - (id)initWithName:(NSString *)uniformName
     152             :          shaderProgram:(OOShaderProgram *)shaderProgram
     153             :          boundToObject:(id<OOWeakReferenceSupport>)target
     154             :                   property:(SEL)selector
     155             :         convertOptions:(OOUniformConvertOptions)options
     156             : {
     157             :         BOOL                                    OK = YES;
     158             :         
     159             :         if (EXPECT_NOT(uniformName == NULL || shaderProgram == NULL || selector == NULL)) OK = NO;
     160             :         
     161             :         if (OK)
     162             :         {
     163             :                 self = [super init];
     164             :                 if (self == nil) OK = NO;
     165             :         }
     166             :         
     167             :         if (OK)
     168             :         {
     169             :                 location = glGetUniformLocationARB([shaderProgram program], [uniformName UTF8String]);
     170             :                 if (location == -1)
     171             :                 {
     172             :                         OK = NO;
     173             :                         OOLog(@"shader.uniform.bind.failed", @"Could not bind uniform \"%@\" to -[%@ %@] (no uniform of that name could be found).", uniformName, [target class], NSStringFromSelector(selector));
     174             :                 }
     175             :         }
     176             :         
     177             :         // If we're still OK, it's a bindable method.
     178             :         if (OK)
     179             :         {
     180             :                 name = [uniformName retain];
     181             :                 isBinding = YES;
     182             :                 value.binding.selector = selector;
     183             :                 
     184             :                 convertClamp = (options & kOOUniformConvertClamp) != 0;
     185             :                 convertNormalize = (options & kOOUniformConvertNormalize) != 0;
     186             :                 convertToMatrix = (options & kOOUniformConvertToMatrix) != 0;
     187             :                 bindToSuper = (options & kOOUniformBindToSuperTarget) != 0;
     188             :                 
     189             :                 if (target != nil)  [self setBindingTarget:target];
     190             :         }
     191             :         
     192             :         if (!OK)
     193             :         {
     194             :                 [self release];
     195             :                 self = nil;
     196             :         }
     197             :         return self;
     198             : }
     199             : 
     200             : 
     201             : - (void)dealloc
     202             : {
     203             :         [name release];
     204             :         if (isBinding)  [value.binding.object release];
     205             :         
     206             :         [super dealloc];
     207             : }
     208             : 
     209             : 
     210             : - (NSString *)description
     211             : {
     212             :         NSString                                        *valueDesc = nil;
     213             :         NSString                                        *valueType = nil;
     214             :         id                                                      object;
     215             :         
     216             :         if (isBinding)
     217             :         {
     218             :                 object = [value.binding.object weakRefUnderlyingObject];
     219             :                 if (object != nil)
     220             :                 {
     221             :                         valueDesc = [NSString stringWithFormat:@"[<%@ %p> %@]", [object class], value.binding.object, NSStringFromSelector(value.binding.selector)];
     222             :                 }
     223             :                 else
     224             :                 {
     225             :                         valueDesc = @"0";
     226             :                 }
     227             :         }
     228             :         else
     229             :         {
     230             :                 switch (type)
     231             :                 {
     232             :                         case kOOShaderUniformTypeInt:
     233             :                                 valueDesc = [NSString stringWithFormat:@"%i", value.constInt];
     234             :                                 break;
     235             :                         
     236             :                         case kOOShaderUniformTypeFloat:
     237             :                                 valueDesc = [NSString stringWithFormat:@"%g", value.constFloat];
     238             :                                 break;
     239             :                                 
     240             :                         case kOOShaderUniformTypeVector:
     241             :                                 {
     242             :                                         Vector v = { value.constVector[0], value.constVector[1], value.constVector[2] };
     243             :                                         valueDesc = VectorDescription(v);
     244             :                                 }
     245             :                                 break;
     246             :                                 
     247             :                         case kOOShaderUniformTypeMatrix:
     248             :                                 valueDesc = OOMatrixDescription(value.constMatrix);
     249             :                                 break;
     250             :                 }
     251             :         }
     252             :         
     253             :         switch (type)
     254             :         {
     255             :                 case kOOShaderUniformTypeChar:
     256             :                 case kOOShaderUniformTypeUnsignedChar:
     257             :                 case kOOShaderUniformTypeShort:
     258             :                 case kOOShaderUniformTypeUnsignedShort:
     259             :                 case kOOShaderUniformTypeInt:
     260             :                 case kOOShaderUniformTypeUnsignedInt:
     261             :                 case kOOShaderUniformTypeLong:
     262             :                 case kOOShaderUniformTypeUnsignedLong:
     263             :                         valueType = @"int";
     264             :                         break;
     265             :                 
     266             :                 case kOOShaderUniformTypeFloat:
     267             :                 case kOOShaderUniformTypeDouble:
     268             :                         valueType = @"float";
     269             :                         break;
     270             :                         
     271             :                 case kOOShaderUniformTypeVector:
     272             :                 case kOOShaderUniformTypeHPVector:
     273             :                         valueType = @"vec4";
     274             :                         break;
     275             :                         
     276             :                 case kOOShaderUniformTypeQuaternion:
     277             :                         valueType = @"vec4 (quaternion)";
     278             :                         break;
     279             :                         
     280             :                 case kOOShaderUniformTypeMatrix:
     281             :                         valueType = @"matrix";
     282             :                         break;
     283             :                         
     284             :                 case kOOShaderUniformTypePoint:
     285             :                         valueType = @"vec2";
     286             :                         break;
     287             :                         
     288             :                 case kOOShaderUniformTypeObject:
     289             :                         valueType = @"object-binding";
     290             :                         break;
     291             :                         
     292             :         }
     293             :         if (valueType == nil)  valueDesc = @"INVALID";
     294             :         if (valueDesc == nil)  valueDesc = @"INVALID";
     295             :         
     296             :         /*      Examples:
     297             :                         <OOShaderUniform 0xf00>{1: int tex1 = 1;}
     298             :                         <OOShaderUniform 0xf00>{3: float laser_heat_level = [<ShipEntity 0xba8> laserHeatLevel];}
     299             :         */
     300             :         return [NSString stringWithFormat:@"<%@ %p>{%i: %@ %@ = %@;}", [self class], self, location, valueType, name, valueDesc];
     301             : }
     302             : 
     303             : 
     304             : - (void)apply
     305             : {
     306             :         
     307             :         if (isBinding)
     308             :         {
     309             :                 if (isActiveBinding)  [self applyBinding];
     310             :         }
     311             :         else  [self applySimple];
     312             : }
     313             : 
     314             : 
     315             : - (void)setBindingTarget:(id<OOWeakReferenceSupport>)target
     316             : {
     317             :         BOOL                                    OK = YES;
     318             :         NSMethodSignature               *signature = nil;
     319             :         NSUInteger                              argCount;
     320             :         NSString                                *methodProblem = nil;
     321             :         id<OOWeakReferenceSupport> superCandidate = nil;
     322             :         
     323             :         if (!isBinding)  return;
     324             :         
     325             :         // Resolve "supertarget" if applicable
     326             :         if (bindToSuper)
     327             :         {
     328             :                 for (;;)
     329             :                 {
     330             :                         if (![target respondsToSelector:@selector(superShaderBindingTarget)])  break;
     331             :                         
     332             :                         superCandidate = [(id)target superShaderBindingTarget];
     333             :                         if (superCandidate == nil || superCandidate == target)  break;
     334             :                         target = superCandidate;
     335             :                 }
     336             :         }
     337             :         
     338             :         [value.binding.object release];
     339             :         value.binding.object = [target weakRetain];
     340             :         
     341             :         if (target == nil)
     342             :         {
     343             :                 isActiveBinding = NO;
     344             :                 return;
     345             :         }
     346             :         
     347             :         if (OK)
     348             :         {
     349             :                 if (![target respondsToSelector:value.binding.selector])
     350             :                 {
     351             :                         methodProblem = @"target does not respond to selector";
     352             :                         OK = NO;
     353             :                 }
     354             :         }
     355             :         
     356             :         if (OK)
     357             :         {
     358             :                 value.binding.method = [(id)target methodForSelector:value.binding.selector];
     359             :                 if (value.binding.method == NULL)
     360             :                 {
     361             :                         methodProblem = @"could not retrieve method implementation";
     362             :                         OK = NO;
     363             :                 }
     364             :         }
     365             :         
     366             :         if (OK)
     367             :         {
     368             :                 signature = [(id)target methodSignatureForSelector:value.binding.selector];
     369             :                 if (signature == nil)
     370             :                 {
     371             :                         methodProblem = @"could not retrieve method signature";
     372             :                         OK = NO;
     373             :                 }
     374             :         }
     375             :         
     376             :         if (OK)
     377             :         {
     378             :                 argCount = [signature numberOfArguments];
     379             :                 if (argCount != 2)      // "no-arguments" methods actually take two arguments, self and _msg.
     380             :                 {
     381             :                         methodProblem = @"only methods which do not require arguments may be bound to";
     382             :                         OK = NO;
     383             :                 }
     384             :         }
     385             :         
     386             :         if (OK)
     387             :         {
     388             :                 type = OOShaderUniformTypeFromMethodSignature(signature);
     389             :                 if (type == kOOShaderUniformTypeInvalid)
     390             :                 {
     391             :                         OK = NO;
     392             :                         methodProblem = [NSString stringWithFormat:@"unsupported type \"%s\"", [signature methodReturnType]];
     393             :                 }
     394             :         }
     395             :         
     396             :         isActiveBinding = OK;
     397             :         if (!OK)  OOLog(@"shader.uniform.bind.failed", @"Shader could not bind uniform \"%@\" to -[%@ %@] (%@).", name, [target class], NSStringFromSelector(value.binding.selector), methodProblem);
     398             : }
     399             : 
     400             : @end
     401             : 
     402             : 
     403             : @implementation OOShaderUniform (OOPrivate)
     404             : 
     405             : // Designated initializer.
     406             : - (id)initWithName:(NSString *)uniformName shaderProgram:(OOShaderProgram *)shaderProgram
     407             : {
     408             :         BOOL                                    OK = YES;
     409             :         
     410             :         if (EXPECT_NOT(uniformName == NULL || shaderProgram == NULL)) OK = NO;
     411             :         
     412             :         if (OK)
     413             :         {
     414             :                 self = [super init];
     415             :                 if (self == nil) OK = NO;
     416             :         }
     417             :         
     418             :         if (OK)
     419             :         {
     420             :                 location = glGetUniformLocationARB([shaderProgram program], [uniformName UTF8String]);
     421             :                 if (location == -1)  OK = NO;
     422             :         }
     423             :         
     424             :         if (OK)
     425             :         {
     426             :                 name = [uniformName copy];
     427             :         }
     428             :         
     429             :         if (!OK)
     430             :         {
     431             :                 [self release];
     432             :                 self = nil;
     433             :         }
     434             :         return self;
     435             : }
     436             : 
     437             : - (void)applySimple
     438             : {
     439             :         switch (type)
     440             :         {
     441             :                 case kOOShaderUniformTypeInt:
     442             :                         OOGL(glUniform1iARB(location, value.constInt));
     443             :                         break;
     444             :                 
     445             :                 case kOOShaderUniformTypeFloat:
     446             :                         OOGL(glUniform1fARB(location, value.constFloat));
     447             :                         break;
     448             :                 
     449             :                 case kOOShaderUniformTypeVector:
     450             :                         OOGL(glUniform4fvARB(location, 1, value.constVector));
     451             :                         break;
     452             :                 
     453             :                 case kOOShaderUniformTypeMatrix:
     454             :                         GLUniformMatrix(location, value.constMatrix);
     455             :         }
     456             : }
     457             : 
     458             : 
     459             : - (void)applyBinding
     460             : {
     461             :         
     462             :         id                                                      object = nil;
     463             :         GLint                                           iVal;
     464             :         GLfloat                                         fVal;
     465             :         Vector                                          vVal;
     466             :         HPVector                                        hpvVal;
     467             :         GLfloat                                         expVVal[4];
     468             :         OOMatrix                                        mVal;
     469             :         Quaternion                                      qVal;
     470             :         NSPoint                                         pVal = {0};
     471             :         BOOL                                            isInt = NO, isFloat = NO, isVector = NO, isMatrix = NO, isPoint = NO;
     472             :         id                                                      objVal = nil;
     473             :         
     474             :         /*      Design note: if the object has been dealloced, or an exception occurs,
     475             :                 do nothing. Shaders can specify a default value for uniforms, which
     476             :                 will be used when no setting has been provided by the host program.
     477             :                 
     478             :                 I considered clearing value.binding.object if the underlying object is
     479             :                 gone, but adding code to save a small amount of spacein a case that
     480             :                 shouldn't occur in normal usage is silly.
     481             :         */
     482             :         object = [value.binding.object weakRefUnderlyingObject];
     483             :         if (object == nil)  return;
     484             :         
     485             :         switch (type)
     486             :         {
     487             :                 case kOOShaderUniformTypeChar:
     488             :                 case kOOShaderUniformTypeUnsignedChar:
     489             :                 case kOOShaderUniformTypeShort:
     490             :                 case kOOShaderUniformTypeUnsignedShort:
     491             :                 case kOOShaderUniformTypeInt:
     492             :                 case kOOShaderUniformTypeUnsignedInt:
     493             :                 case kOOShaderUniformTypeLong:
     494             :                 case kOOShaderUniformTypeUnsignedLong:
     495             :                         iVal = (GLint)OOCallIntegerMethod(object, value.binding.selector, value.binding.method, type);
     496             :                         isInt = YES;
     497             :                         break;
     498             :                 
     499             :                 case kOOShaderUniformTypeFloat:
     500             :                 case kOOShaderUniformTypeDouble:
     501             :                         fVal = OOCallFloatMethod(object, value.binding.selector, value.binding.method, type);
     502             :                         isFloat = YES;
     503             :                         break;
     504             :                 
     505             :                 case kOOShaderUniformTypeVector:
     506             :                         vVal = ((VectorReturnMsgSend)value.binding.method)(object, value.binding.selector);
     507             :                         if (convertNormalize)  vVal = vector_normal(vVal);
     508             :                         expVVal[0] = vVal.x;
     509             :                         expVVal[1] = vVal.y;
     510             :                         expVVal[2] = vVal.z;
     511             :                         expVVal[3] = 1.0f;
     512             :                         isVector = YES;
     513             :                         break;
     514             : 
     515             :                 case kOOShaderUniformTypeHPVector:
     516             :                         hpvVal = ((HPVectorReturnMsgSend)value.binding.method)(object, value.binding.selector);
     517             :                         if (convertNormalize)  hpvVal = HPvector_normal(hpvVal);
     518             :                         expVVal[0] = (GLfloat)hpvVal.x;
     519             :                         expVVal[1] = (GLfloat)hpvVal.y;
     520             :                         expVVal[2] = (GLfloat)hpvVal.z;
     521             :                         expVVal[3] = 1.0f;
     522             :                         isVector = YES;
     523             :                         break;
     524             :                 
     525             :                 case kOOShaderUniformTypeQuaternion:
     526             :                         qVal = ((QuaternionReturnMsgSend)value.binding.method)(object, value.binding.selector);
     527             :                         if (convertToMatrix)
     528             :                         {
     529             :                                 mVal = OOMatrixForQuaternionRotation(qVal);
     530             :                                 isMatrix = YES;
     531             :                         }
     532             :                         else
     533             :                         {
     534             :                                 expVVal[0] = qVal.x;
     535             :                                 expVVal[1] = qVal.y;
     536             :                                 expVVal[2] = qVal.z;
     537             :                                 expVVal[3] = qVal.w;
     538             :                                 isVector = YES;
     539             :                         }
     540             :                         break;
     541             :                 
     542             :                 case kOOShaderUniformTypeMatrix:
     543             :                         mVal = ((MatrixReturnMsgSend)value.binding.method)(object, value.binding.selector);
     544             :                         isMatrix = YES;
     545             :                         break;
     546             :                 
     547             :                 case kOOShaderUniformTypePoint:
     548             :                         pVal = ((PointReturnMsgSend)value.binding.method)(object, value.binding.selector);
     549             :                         isPoint = YES;
     550             :                         break;
     551             :                 
     552             :                 case kOOShaderUniformTypeObject:
     553             :                         objVal = ((ObjectReturnMsgSend)value.binding.method)(object, value.binding.selector);
     554             :                         if ([objVal isKindOfClass:[NSNumber class]])
     555             :                         {
     556             :                                 fVal = [objVal floatValue];
     557             :                                 isFloat = YES;
     558             :                         }
     559             :                         else if ([objVal isKindOfClass:[OOColor class]])
     560             :                         {
     561             :                                 OOColor *color = objVal;
     562             :                                 expVVal[0] = [color redComponent];
     563             :                                 expVVal[1] = [color greenComponent];
     564             :                                 expVVal[2] = [color blueComponent];
     565             :                                 expVVal[3] = [color alphaComponent];
     566             :                                 isVector = YES;
     567             :                         }
     568             :                         break;
     569             :         }
     570             :         
     571             :         if (isFloat)
     572             :         {
     573             :                 if (convertClamp)  fVal = OOClamp_0_1_f(fVal);
     574             :                 OOGL(glUniform1fARB(location, fVal));
     575             :         }
     576             :         else if (isInt)
     577             :         {
     578             :                 if (convertClamp)  iVal = iVal ? 1 : 0;
     579             :                 OOGL(glUniform1iARB(location, iVal));
     580             :         }
     581             :         else if (isPoint)
     582             :         {
     583             :                 GLfloat v2[2] = { pVal.x, pVal.y };
     584             :                 OOGL(glUniform2fvARB(location, 1, v2));
     585             :         }
     586             :         else if (isVector)
     587             :         {
     588             :                 OOGL(glUniform4fvARB(location, 1, expVVal));
     589             :         }
     590             :         else if (isMatrix)
     591             :         {
     592             :                 GLUniformMatrix(location, mVal);
     593             :         }
     594             : }
     595             : 
     596             : @end
     597             : 
     598             : #endif // OO_SHADERS

Generated by: LCOV version 1.14